XPLMProcessing

To use:

import xp

This API allows you to get regular callbacks during the flight loop, the part of X-Plane where the plane’s position calculates the physics of flight, etc. Use these APIs to accomplish periodic tasks like logging data and performing I/O.

Warning

Do not use these callbacks to draw! You cannot draw during flight loop callbacks. Use the drawing callbacks (see XPLMDisplay module for more info) for graphics.

Timing Functions

getElapsedTime()

Return the elapsed time since the sim started up, in floating point seconds. This is continues to count upward even if the sim is paused.

Warning

getElapsedTime() is not a very good timer! It lacks precision in both its data type and its source. Do not attempt to use it for time critical applications like network multiplayer.

>>> xp.getElapsedTime()
196.7588833

Official SDK XPLMGetElapsedTime

getCycleNumber()

Return an integer counter starting at zero for each sim cycle computed/video frame rendered.

>>> xp.getCycleNumber()
29776

Official SDK XPLMGetCycleNumber

FlightLoop Functions

There are two sets of flight loop functions. The “new” way is a bit simpler, and allows you to specify phase.

Task

New (flightLoopID)

Old (callback + refCon)

Create / Register

createFlightLoop()

registerFlightLoopCallback()

Reschedule

scheduleFlightLoop()

setFlightLoopCallbackInterval()

Destroy / Unregister

destroyFlightLoop()

unregisterFlightLoopCallback()

FlightLoop - New Style

createFlightLoop(callback, phase=0, refCon=None)

Create a flightloop callback and return a flightLoopID which can be used to change or destroy it.

The flight loop callback is initialized as unscheduled: You’ll need to call scheduleFlightLoop().

Your callback function takes four parameters and must return an interval. Official SDK XPLMFlighLoop_f

callback(sinceLast, elapsedTime, counter, refCon)

sinceLast is wall time (seconds) since your last callback.

elapsedTime is wall time (seconds) since start of sim. This appears to be identical to current value of getElapsedTime().

counter is a monotonically increasing counter, bumped once per flight loop dispatched from the sim. It appears to be identical to the current cycle (getCycleNumber()). Note that “cycle” rate and “flightloop” rate are not the same. Commonly, two cycles are consumed between calls to the flight loop.

refCon is the same reference constant passed on creation.

Your callback must return a floating point value for the “next” interval (This is identical to value in scheduleFlightLoop()):

  • 0= stop receving callbacks

  • >0 number of seconds until next callback

  • <0 number of flightloops until next callback

Note

Laminar documentation indicates the second parameter to the callback is

inElapsedTimeSinceLastFlightLoop: the wall time since any flight loop was dispatched.

This is not correct: it is total sim elapsed time independent of your callback.

phase is one of XPLMFlightLoopPhaseType, to have your callback run before or after X-Plane integrates the flight model.

Try to run your flight loop as infrequently as is practical, and suspend it (using return value 0) when you do not need it; lots of flight loop callbacks that do nothing lowers X-Plane’s frame rate.

Your callback will NOT be unregistered if you return 0; it will merely be inactive.

>>> def MyCallback(lastCall, elapsedTime, counter, refCon):
...    xp.log(f"{elapsedTime}, {counter}")
...    return 1.0
...
>>> myRefCon = {'data': []}
>>> flightLoopID = xp.createFlightLoop(MyCallback, refCon=myRefCon)
>>> flightLoopID
<capsule object "FlightLoopIDRef" at 0x7fa89eb15720>
>>> xp.scheduleFlightLoop(flightLoopID, -1)
>>> xp.destroyFlightLoop(flightLoopID)

To mimic the C-API, you can alternatively call createFlightLoop() with a single, three-element tuple matching the createFlightLoop() parameters described above:

params = (
  phase,
  callback,
  refCon
)
>>> myRefCon = {'data': []}
>>> flightLoopID = xp.createFlightLoop([None, MyCallback, myRefCon])

Official SDK XPLMCreateFlightLoop

destroyFlightLoop(flightLoopID)

This routine destroys a flight loop callback specified by flightLoopID. Only call it on flight loops created with createFlightLoop().

>>> flightLoopID = xp.createFlightLoop(MyCallback)
>>> xp.destroyFlightLoop(flightLoopID)

Official SDK XPLMDestroyFlightLoop

scheduleFlightLoop(flightLoopID, interval, relativeToNow=1)

Change the interval associated with your flightLoopID received from createFlightLoop().

interval is set to:

Positive number

indicates seconds from registration time to the next callback.

For example pass 10 to be called (approximately) 10 seconds from now.

Negative number

indicates number of FlightLoops to next callback.

For example pass -1 to be called at the next cycle

Zero

Deactivate flight loop. Flight loop remains registered, but is not called.

If relativeToNow is 1, the interval value is relative to now, e.g., interval=10.0 indicates run the callback ten seconds from “now”. Otherwise, time (or #flight loops) is relative the previous execution of this callback (or when it was created/registered, if not yet ever run).

Note that this schedules the flight loop once. Your flight loop callback, itself, returns the next value for interval.

>>> flightLoopID = xp.createFlightLoop(MyCallback)
>>> xp.scheduleFlightLoop(flightLoopID, interval=10)

Note

THREAD SAFETY: it is legal to call this routine from any thread under the following conditions:

  1. The call must be between the beginning of an XPluginEnable and the end of an XPluginDisable sequence. (That is, you must not call this routine from thread activity when your plugin was supposed to be disabled. Since plugins are only enabled while loaded, this also implies you cannot run this routine outside an XPluginStart/XPluginStop sequence.)

  2. You may not call this routine re-entrantly for a single flight loop ID. (That is, you can’t enable from multiple threads at the same time.)

  3. You must call this routine between the time after createFlightLoop() returns a value and the time you call destroyFlightLoop(). (That is, you must ensure that your threaded activity is within the life of the object. The SDK does not check this for you, nor does it synchronize destruction of the object.)

  4. The object must be unscheduled if this routine is to be called from a thread other than the main thread.

Official SDK XPLMScheduleFlightLoop

FlightLoop - Old Style

registerFlightLoopCallback(callback, interval=0.0, refCon=None)

Register your flight loop callback, see createFlightLoop() for information about the callback function.

interval is defines when you will be called next:
  • 0= deactivate

  • >0 seconds

  • <0 flightLoops

>>> def MyCallback(lastCall, elapsedTime, counter, refCon):
...    xp.log(f"{elapsedTime}, {counter}")
...    return 1.0
...
>>> xp.registerFlightLoopCallback(MyCallback, interval=-1)

Official SDK XPLMRegisterFlightLoopCallback

unregisterFlightLoopCallback(callback, refCon=None)

This routine unregisters your flight loop callback. refCon must match value provided with registerFlightLoopCallback() as we use it to find and match the callback.

Do NOT call unregisterFlightLoopCallback() from within your flight loop callback. (Set interval to zero instead.)

Once your callback is unregistered, it will not be called again.

>>> myRefCon = {'data': []}
>>> xp.registerFlightLoopCallback(MyCallback, interval=-1, refCon=myRefCon}
>>> xp.unregisterFlightLoopCallback(MyCallback, myRefCon)

Official SDK XPLMUnregisterFlightLoopCallback

setFlightLoopCallbackInterval(callback, interval, relativeToNow=1, refCon=None)

Change the interval asscociated with your callback. (Must have already been registered with registerFlightLoopCallback().)

This is equivalent to scheduleFlightLoop(), but uses callback + refCon to internally locate your callback.

Do not call setFlightLoopCallbackInterval() from your callback; use the return value of the callback to change your callback interval from inside your callback.

Note

This does not register or change your callback, it merely changes the timing of the next call. Your callback and refCon much match values registered.

>>> def MyCallback(lastCall, elapsedTime, counter, refCon):
...    xp.log(f"{elapsedTime}, {counter}")
...    return 1.0
...
>>> myRefCon = {'data': []}
>>> xp.registerFlightLoopCallback(MyCallback, interval=0, refCon=myRefCon)
>>> xp.setFlightLoopCallbackInterval(MyCallback, interval=10, refCon=myRefCon)

Official SDK XPLMSetFlightLoopCallbackInterval

Constants

FlightLoopID

Opaque identifier for a flight loop callback. You can use this identifier to easily track and remove your callbacks using new flight loop APIs.

Official SDK XPLMFlightLoopID

XPLMFlightLoopPhaseType

You can register a flight loop callback to run either before or after the flight model is integrated by X-Plane.

FlightLoop_Phase_BeforeFlightModel = 0

Your callback runs before X-Plane integrates the flight model.

Official SDK xplm_FlightLoop_Phase_BeforeFlightModel

FlightLoop_Phase_AfterFlightModel = 1

Your callback runs after X-Plane integrates the flight model.

Official SDK xplm_FlightLoop_Phase_AfterFlightModel