article_type: Guide

Tuning Idle Speeds

Setting up idle speed is a four-step process:

  1. Setting the minimum “smooth” running speed.
  2. Getting the internal friction right.
  3. Setting the right amount of throttle to overcome the internal friction.
  4. Setting the fuel flow for that idle throttle

The “minimum engine running speed” setting in Plane Maker does NOT set the idle speed itself, but the minimum engine RPM that results in a smooth operation. This speed is lower than what we want the engine to actually idle at. If the RPM falls below the minimum running speed we will experience “stumbling” that manifests in RPM and torque fluctuations. If RPM drops far enough below that minimum speed, combustion itself will be affected and unable to sustain engine operation at all. The engine will come to a halt. The strength of the stumbling effect at lower-than-minimum RPM is determined by the number of cylinders that is set in Plane Maker. A four cylinder engine will exhibit more stumbling than a 6 cylinder engine or a radial engine with even more cylinders.

For a typical flat-four engine, the target idle will be around 600-700 RPM, while the minimum running RPM should be set closer to 500. This provides a good margin to keep the engine running under load from the alternator and at higher altitudes and hotter days where the engine makes less power. If the RPM drops below that setting of 500, expect erratic engine behavior.

The idle throttle setting serves one purpose, and that is overcoming the engine’s internal friction. The idle speed of the engine is determined by the equilibrium of the torque produced by the engine at idle throttle setting and the torque consumed by the engine at idle. That torque that needs to be overcome is the engine’s own internal friction, plus the small torque consumed by the propeller rotating at slow speed, plus any additional loads from the generator the engine needs to turn.

The engine’s internal friction is controlled in Plane Maker with the “engine friction” ratio. X-Plane’s guess at 1.0 works for a big-bore high compression direct-drive engine such as the IO-550 found on a Cirrus or Columbia. Other engines with different compression ratios or gearing will likely require different values here.

A good way to find the right internal friction, if the propeller is set up correctly, is to turn the engine off in flight (by cutting the mixture) and slowing the aircraft down to just above stall speed. The engine should almost stop turning as the airplane approaches stall speed, but rotate practically unaffected at greater air speeds (note that once fully stopped, a disproportionately high airspeed is needed to get the prop turning again).

The suggested process is to tune the sim/aircraft2/engine/engine_friction_ratio dataref in the simulator, take note of the value that produces the desired result, and then set it to the acf permanently in Plane Maker.

Once the internal friction is set, the airplane should be placed at a sea-level airport in standard atmosphere (15C OAT, 1013hPA QNH) and the electrical system loaded up with all electrical loads that are reasonably expected to be on on the ground ready for take-off, that is avionics bus powered, navigation and landing lights on, etc.

Then the idle throttle adjustment (sim/aircraft2/engine/high_idle_ratio) should be made so that the engine runs at a minimum smooth idle RPM with the throttle all the way out.

This will likely be too low to run the generator or alternator enough to charge the battery. That is not a bug, but corresponds to behavior found on many real piston aircraft. Basically all real piston engines require a positive throttle input to run at a high enough RPM to sustain generator load to charge the battery along with other electrical loads.

It is important to let the engine run for a minute or longer, as it might take some time to find the equilibrium between drive torque (generated by the engine) and drag torque (consumed by the engine itself, the propeller, and the generator).

The idle should be tweaked in the simulator with the sim/aircraft2/engine/high_idle_ratio dataref, and the desired value then set permanently in Plane Maker.
Once the engine runs stable at a low RPM in this config, it is up to the user (i.e. pilot, not aircraft developer) to run the throttle up enough to sustain battery charging.

Finally, the desired fuel flow at this setting can be adjusted with the dataref sim/aircraft/overflow/ff_rat_idle_PRP in the simulator and permanently saved to the acf in Plane Maker on the SFC (specific fuel consumption) tab.

Note that setting the engine up like this corresponds to a sea-level setup as would be performed on most aircraft.

Taking this aircraft to a high elevation airport such as Leadville, CO, will result in the engine stumbling or maybe even stopping at idle in a very short period of time. That is not a bug, but corresponds to how a real aircraft would behave at high density altitudes. It is absolutely necessary to lean the mixture and increase the throttle to sustain a good idle at high density altitudes, both in the real world and in X-Plane. In practice, the pilot will add throttle to keep the engine running, then slowly pull out the mixture control and watch the tachometer, to lean the engine to peak RPM, then reduce the throttle again to the desired RPM as dictated by electrical needs.

Comments Off on Tuning Idle Speeds

Testing in X-Plane

This document outlines how to test X-Plane via CLI commands and telnet.

Laminar Research develops tests via telnet, then passes them to X-Plane via script.

Using telnet

Launch X-Plane with the CLI flag

--testing

Then connect to the sim using the CLI command

telnet localhost 49000

List of Commands

acf <string>

Loads the aircraft at the specified path (be sure to use quotes). Ex: acf “Aircraft/Laminar Research/Cessna 172SP/Cessna_172SP_G1000.acf”

move lle <latitude> <longitude> <elevation in meters>

Reposition your plane at an exact lat/lon/elevation. Note: aircraft will be initialized with 0 airspeed, so this is best used on the ground if possible.

move <ICAO> <optional ramp start>

Reposition the aircraft at the specified airport. Defaults to runway 0, unless a ramp start is specified.

command <command> <optional time in seconds>

Execute the specified command for the specified duration, in seconds. See Commands.txt for the full list of commands. Note that the test runner is incredibly fast, so it’s recommended to add a

wait

(see below) after each command.

Datarefs

dref set <dataref> <value>

Set a dataref & value. See DataRefs.txt for the full list of datarefs.

expect <dataref> <conditional> <value>

Checks that the specified dataref meets an expected value. Ex. expect sim/flightmodel/engine/ENGN_running[0] == 1

wait <time in seconds, can be a decimal>

Waits the specified time before executing the next line. Important to use after commands to ensure it fully completes before moving on. Waiting longer times, such as multiple minutes, after a move or aircraft load can be useful to ensure all aspects of a flight stabilize.

camera dump

Outputs current camera location to telnet.

camera <additional params>

Sets specific camera location. (Recommended to get the exact command from camera dump.)

quit

Quit the sim. Also useful to reset parameters between tests.

Writing & Running tests

Test files must include the following header:

A
1000
CLI_SCRIPT

Save your test script as a .txt or .test file.

Use the command line argument

--script=[file name]

To launch X-Plane and run your test script. Note that X-Plane will use the existing preferences at launch. If there are syntax errors in your script, X-Plane will print the error in the terminal (Mac only) and log.txt for investigation. The results of the test run will be output in the same places as well. Finally, tests that fail any “expect <dataref>” lines will automatically save a screenshot at the fail point in the main X-Plane directory.

Example Script

Download a sample script here.

1 Comment

Plugin Guidance for OpenGL Drawing

This document provides guidelines for using OpenGL to draw from X-Plane plugins running inside X-Plane’s process.

While X-Plane can use OpenGL, Vulkan, or Metal drivers to render to a graphics card, plugin-drawing is supported only via OpenGL. OpenGL is not the fastest or most modern API, but it does provide a robust way to draw in 3-d without exposing complicated and error prone implementation details like memory management, resource barriers, or concurrency, making it an appropriate choice for custom user interface and custom aircraft glass displays.

General principles

In our work with third party add-ons, we see three kinds of add-on behavior that cause almost all of the compatibility problems, bugs, performance loss, and crashes. Here are three guiding principles for interacting with X-Plane.

Do Not Lie to X-Plane

If your add-on uses plugin APIs for purposes other than their intended uses, you may have performance or compatibility problems later. Avoid things like using drawing callbacks for non-drawing purposes, using 3-d drawing callbacks for 2-d drawing, or non-window callbacks for UI.

If your add-on lies to X-Plane about your intentions, X-Plane no longer has optimal situational awareness and can no longer run plugins in an optimal way. Achieving the best possible performance is only possible if everyone plays fair and by the rules.

Minimize XPLM and OpenGL Use

X-Plane users care deeply about performance; minimize your use of OpenGL and the XPLM to minimize your add-on’s negative impact on framerate. Only perform operations that are necessary, and cache values retrieved through XPLM API, except for OpenGL resources, to be reused later if possible. When drawing, avoid repeated OpenGL state changes and adopt modern OpenGL techniques where feasible. Using shaders and vertex buffer objects for static geometry is much faster than using pre OpenGL 2.0 immediate mode rendering.

Do Not Use Undocumented Behavior

Do not use the SDK in ways that are not covered by the documentation; undocumented use of the SDK can appear to work but destabilize the sim or interfere with other add-ons, or can break in a future X-Plane update. If you are not sure from the documentation whether something is legal, ask us!

Drawing Callbacks

Plugins receive an opportunity to draw inside X-Plane via drawing callbacks; the following section provides guidelines for when and how to use drawing callbacks correctly.

Register only the drawing callbacks that you need at the time you need them to do actual drawing! Dispatching any drawing callback requires a not-insignificant CPU time overhead and requires heavy synchronization in the case of Vulkan and Metal, both of which are completely wasted if no drawing actually happens.

Use Drawing Callbacks Only for Drawing

Use drawing callbacks only for drawing, not for updating simulation state, bookkeeping, network IO, etc. Drawing callbacks can be called multiple or zero times per frame based on the user’s monitor configuration, so add-ons that use drawing callbacks for other purposes both hurt performance and may not work correctly in some situations.

Use Real Windows for UI

Using real windows and the XPLM 3.x window API (XPLMCreateWindowEx, etc.) is highly recommended over using legacy draw callbacks. This provides the sim with the most situational awareness to improve dispatching and compositing of plugin windows. The real window API also provides correct UI interaction for floating windows and focus.

Use Drawing Callbacks for Panels

The panel and gauge drawing callbacks let you draw under or on top of the 2-d and 3-d panel. Be sure to check the draw-type datarefs for the callbacks – see Datarefs for Panel Drawing below. Your panel draw callback can be called for both the albedo layer and the emissive layer of the panel separately; make sure your code draws the appropriate content for each.

Use a Flight Loop Callback for Off-Screen FBOs

Use a flight loop callback to draw into your offscreen framebuffer. When you do this, X-Plane will not have set an FBO up for you to draw into, so you will bypass the overhead of synchronizing with our drawing on the GPU.

Use XPLMInstance and Particles for 3-d Drawing Where Possible

Avoid using the 3D drawing callbacks unless absolutely necessary. Dispatching 3D drawing callbacks comes with potentially negative performance impacts and isn’t necessary most of the time.

The best interface for drawing “stuff” in the 3-d world is the XPLM instancing API to draw objects into the world or tie particle effects to your custom datarefs in order to create custom effects. The instancing API is straightforward to use, available since X-Plane 11.0, and replaces XPLMDrawObject and XPLMDrawAircraft.

See also the Plugin Compatibility Guide for X-Plane 11.50.

Use a 2-d Callback for “Coach Marks”

When drawing overlays or other kinds of scene annotations, a 2D drawing callback is much better suited than a 3D drawing callback. You can use the projection matrices provided by X-Plane to efficiently transform 3D coordinates to 2D screen coordinates.

A sample of this can be found here: //developer.x-plane.com/code-sample/coachmarks/

See also the Plugin Compatibility Guide for X-Plane 11.50.

Use a Panel Texture to Draw “on” the Aircraft

If you need to draw onto the aircraft, e.g. to simulate damage to the fuselage, rain on a wind-screen, or a livery change, you can map a panel texture to that section of the aircraft and then use a panel drawing callback for drawing. This can be used for dynamic decals or other effects, for example, that would otherwise require complicated use of the 3D drawing callbacks.

Panel texturing is available for all parts of the aircraft, not just the cockpit object, but is more expensive than using disk-based textures – use it only where the dynamic effect is absolutely necessary.

If your add-on needs more panel texture space, you can use panel regions to get access to four separate dynamic textures.

Use the New 3-d Callback on Windows Only When Necessary

Using the new 3D drawing callback under Vulkan is not recommended unless absolutely necessary! It comes with a lot of gotchas and caveats and is intended only for add ons that truly need to do custom scenery drawing in 3D, like weather add ons. Before using the 3D drawing callback, evaluate all alternatives to see if there isn’t a better solution for what you are trying to achieve.

The new 3-d drawing callback works with OpenGL and Vulkan but not Metal; when running under Vulkan, a number of aspects of the drawing environment will be different:

  • The depth buffer will be in reverse-float-Z, not standard integer format; the clip control will be DirectX style and the depth compare function will be inverted.
  • The origin of the frame buffer may be inverted.

See the appendix for datarefs that let a plugin dynamically detect these conditions.

See also: Plugin Compatibility Guide for X-Plane 11.50.

OpenGL State Management

Your plugin shares an OpenGL context with other plugins and sometimes with X-Plane itself; this section provides guidance on how to change OpenGL state correctly.

Don’t Call glGetXXXX

Do not use glGet to retrieve OpenGL state. This usually results in some kind of stall for the driver and has detrimental effects on performance. For custom state management it is usually much better to potentially set OpenGL state again and then cache that known value for future state changes.

X-Plane provides access to the transform stack (upon entrance to your call stack) and viewports via datarefs, as well as the currently bound FBO (although ideally this should not be changed).

If you need a state that isn’t covered here, please contact us – there may be a different way to approach your rendering code.

Call glGetError in Debug Builds Only

Please call glGetError in debug builds and don’t ship code that breaks the OpenGL state machine. Your plugin should never execute code that leaves an OpenGL error in place.

When shipping your plugin, do notcall glGetError as it can hurt performance. A simple macro that wraps glGetError() calls and makes it easy to toggle usually works best and makes it easy to ship the version of code you want.

If your add-on creates framebuffers, please do check for framebuffer completeness once when you create the FBO; your add-on should not create and destroy FBOs on a regular basis.

Use the XPLM APIs to Manage State Where Possible

The XPLM APIs provide a number of calls to manage state; where these functions exist, please use them; they will avoid setting state multiple times.

  • XPLMSetGraphicsState controls blend enable, fixed function alpha test enable, depth mask and depth test enable, fixed function fog and lighting, and fixed function texture enabling.
  • XPLMBindTexture2d controls the 2-d texture binding point.
  • XPLMGenerateTextureIDs wraps texture object generation.

Restore all Other State Except Attributes When Done

Any OpenGL state other than vertex attributes that is not covered by the APIs above must be restored to its initial state when your callback completes. This includes:

  • Unbinding any bound shaders, VAOs, VBOs and non-2d textures to 0.
  • Restoring the drawing array state (only the fixed function vertex array should be enabled).

You do not need to reset the client array pointerstate, nor should you assume upon entrance to a callback that it contains anything sane.

Restore the Current FBO By Dataref

If you must render to an offscreen FBO in a draw callback for some reason, you must restore the currently active FBO before returning from it. Don’t call glGet() to retrieve it, instead use the sim/graphics/view/current_gl_fbo dataref to figure out what FBO to restore.

XPLMDrawString and Friends May Change State

XPLMDrawString and the other API drawing calls can change all of the states mentioned above; while you do not need to clean up after them, do not assume your own state setup is correct after they have been called.

Illegal OpenGL Usage

The following techniques are not allowed from plugins running inside X-Plane.

Do Not Draw from Non-Drawing Callbacks

Non-drawing callbacks aren’t necessarily dispatched in a way that supports drawing. Drawing in a non drawing callback will lead to undefined behavior with regards to your own rendering and the effects on the rest of the sim.

Do Not Mutate X-Plane’s OpenGL Resources

Resources obtained through the XPLM API should be seen as immutable, with the exception of the contentsof the active FBO during draw callbacks. Attempting to change any internal X-Plane resources can lead to heavily decreased performance or have other unexpected side effects, like crashing.

Do Not Locate and Use Private X-Plane OpenGL Resources

Resources not exposed through the XPLM API are not fair game for use. These resources aren’t guaranteed to remain stable between or even within X-Plane runs or future versions. X-Plane is assumed to be the only consumer of these resources and will not attempt synchronizing with plugins when modifying them.

Do Not Hold on to X-Plane OpenGL Resources

While it might be tempting to hold on to OpenGL resources obtained in previous draw callbacks and then reuse them in other callbacks, doing so can have disastrous consequences. This is especially true under Vulkan and Metal, where resources require special synchronization. If missing, this can lead to driver or system crashes and desktop freezes.

Do Not Change State to Affect X-Plane

Attempting to change OpenGL state to trick X-Plane into rendering differently is heavily discouraged. This can lead to X-Plane doing improper bookkeeping of its own state, which can lead to heavily impacted performance. This is also not guaranteed to work between versions or even between runs and can break at any time.

Performance

This section contains performance guidelines for OpenGL plugins.

Pre-Initialize Your Add-on

Perform heavy initialization at aircraft load or flight start time. At runtime, a plugin should be able to just work without lazily initializing any state or computing expensive look up tables. The goal should be to never add unpredictable latency to the frame time.

Do Less

Avoid unnecessary work; preload resources and precompute expensive results.

Follow standard OpenGL performance practices:

  • Move computing work from fragment to vertex shaders.
  • Reduce API calls that change state.
  • Reduce the number of draw calls by merging them where possible.

Do More but Consistently

Attempting to improve framerate by adopting a flip-flop mechanism where one frame doesn’t do heavy work and the other does is highly discouraged. Schemes like this help nothing with the perceived performance of the sim, on the contrary, the very uneven frame times will have a noticeable impact on the user experience. It is much better to instead do the work every frame and provide a slightly lower but much more consistent framerate. Consistently drawing frames on the screen makes the sim appear much smoother to the user.

Consider Using Multicore

If your add-on needs to compute values per frame that are expensive (e.g. take several milliseconds to compute) and you cannot optimize the computation, consider doing the work on a separate thread.

Moving work to a separate thread in a plugin is quite complex because:

  • The SDK provides no built-in facilities to help with this.
  • No SDK APIs may be called from worker threads you create.
  • You do not have access to the SDK-provided OpenGL context from a worker thread.
  • You cannot block waiting for data completion from an SDK callback.

Typically to make this work you will need to launch a worker thread once and have it block on a semaphore to pick up tasks that can be computed independently without XPLM calls and then returned to the main thread via some kind of thread-safe queue.

Appendix A – DataRefs

This section covers datarefs that can be used to get more information about the rendering environment or interact with X-Plane during drawing callbacks. All callbacks should be resolved via XPLMFindDataref at plugin startup but should be read from inside the drawing callback to get information contextual to a particular draw callback. Read results may be undefined outside of or in the wrong draw callback.

Datarefs for Panel Drawing

These drawing callbacks are appropriate from panel drawing callbacks (before/after panel and gauges).

sim/graphics/view/panel_render_type (int, read-only)

This dataref indicates the type of panel rendering being done:

  • 0 render the entire panel (day time and lit elements with full lighting for 2-d panels)
  • 1 albedo only (render solid elements without lighting)
  • 2 emissive only (render lit elements only)

sim/graphics/view/panel_render_new_blending (int, read-only)

This dataref indicates whether the blending mode for the 3-d panel for the current aircraft is the deprecated, legacy “max” alpha blending mode or the modern preferred alpha blending with correct alpha treatment.

  • 0 blending mode is legacy max mode
  • 1 blending mode is modern

The blending equation for legacy max mode is:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);

The blending equation for modern blending mode is:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,

GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

glBlendEquation(GL_FUNC_ADD);

Modern blending mode will correctly composite multiple translucent elements over a translucent or clear panel; legacy max mode gives incorrect but often acceptable results.

Warning: legacy max mode is deprecated and will be dropped from X-Plane in the future. At that point all aircraft will render using blend mode regardless of the content of their art assets.

Datarefs for Panel Clicking

When the mouse is being used over a 3-d panel (via a region mapped with ATTR_cockpit), the following datarefs provide information about the click location.

sim/graphics/view/click_3d_x (float, read-only)

sim/graphics/view/click_3d_y (float, read-only)

This is the location of the mouse in the UV map coordinates of the underlying object.

sim/graphics/view/click_3d_x_pixels (float, read-only

sim/graphics/view/click_3d_y_pixels (float, read-only)

This is the location of the mouse in panel pixel coordinates, or -1 if the mouse is not over the panel.

For all of these datarefs, they are only valid during draw callbacks for the monitor that the mouse is over. Therefore if your plugin is multi-monitor aware, you need to read these from the draw callback for the window that you are using to capture clicks.

(We do not recommend using these datarefs to implement mouse interactions; to capture clicks on a 2-d screen, use a generic instrument on the panel, or consider a real 3-d manipulator on the object itself.)

Datarefs for Panel Location and Scrolling

The location of the panel is provided via two sets of rectangles during panel and gauge drawing callbacks:

sim/graphics/view/panel_total_pnl_l (float, read-only)

sim/graphics/view/panel_total_pnl_b (float, read-only)

sim/graphics/view/panel_total_pnl_r (float, read-only)

sim/graphics/view/panel_total_pnl_t (float, read-only)

These four datarefs form the total bounds of the panel in the modelview coordinate system of the panel drawing callback. You can use these datarefs from inside a panel drawing callback to “calibrate” the location of your drawing. Due to scrolling of panels, the origin of the panel bitmap is not guaranteed to be in any one location on the panel.

sim/graphics/view/panel_visible_pnl_l (float, read-only)

sim/graphics/view/panel_visible_pnl_b (float, read-only)

sim/graphics/view/panel_visible_pnl_r (float, read-only)

sim/graphics/view/panel_visible_pnl_t (float, read-only)

These four datarefs provide the rectangle within the panel that is visible within the current OpenGL viewport. If the panel does not completely fill the viewport, some values could be outside the total bounds of the panel.

These datarefs can be used to identify which panel region is being rendered, for aircraft that use cockpit panel regions. They can also be used to cull gauge drawing that is not going to be visible.

Note that these datarefs are not the same as the current viewport – they are specified in modelview coordinates – that is, the current transform in effect for OpenGL drawing.

sim/graphics/view/panel_total_win_l (float, read-only)

sim/graphics/view/panel_total_win_b (float, read-only)

sim/graphics/view/panel_total_win_r (float, read-only)

sim/graphics/view/panel_total_win_t (float, read-only)

For 2-d panels that are visible on-screen, these datarefs provide the location of the total panel in modelview coordinates during UI drawing callbacks (e.g. post-window draw callbacks and XPLMDisplay window draw callbacks). These datarefs can be used to calibrate the panel location to user interface elements.

sim/graphics/view/panel_visible_win_l (float, read-only)

sim/graphics/view/panel_visible_win_b (float, read-only)

sim/graphics/view/panel_visible_win_r (float, read-only)

sim/graphics/view/panel_visible_win_t (float, read-only)

These datarefs provide the visible extent of the panel in current modelview coordinates during UI callbacks; they can be used for culling gauges that are drawn in UI layers but must match the panel’s location.

Datarefs for 3-d Drawing Callbacks

These datarefs can be read during 3-d drawing callbacks to find details about 3-d drawing.

sim/graphics/view/world_render_type (int, read-only)

This dataref indicates the type of rendering that X-Plane is trying to accomplish with its 3-d callback. The following render passes are visible to plugins:

  • 0 Regular 3-d rendering pass
  • 1 Prep source imagery for water reflections
  • 3 Render depth for shadow maps
  • 6 Prep source imagery for environment cube maps

3-d draw callbacks may be called more than once, so opting out of drawing based on this enumeration can have performance benefits.

Note: by default only regular 3-d render passes are dispatched to plugins; you must enable the capability “XPLM_WANTS_REFLECTIONS“ to receive other types of 3-d drawing callbacks.

Note: the modern 3-d callback does not dispatch shadows; use XPLM object instances for shadow-casting solid geometry.

sim/graphics/view/plane_render_type (int, read-only)

Before X-Plane 11.40, the aircraft drawing phases were the only ones that correctly separated solid and blended drawing; during an aircraft-phase drawing callback this dataref contains:

  • 1 Solid geometry is being drawn for the aircraft. If HDR is enabled and the drawing pass is normal, drawing is going into the G-Buffer.
  • 2 Blended geometry is being drawn for the aircraft. If HDR is enabled, this will be after the G-Buffer is resolved.

For plugins using the modern 3-d drawing callback, the one callback that a plugin receives is equivalent to a post-aircraft drawing callback for blending. Solid drawing is not available – use instancing to add models to the X-Plane world.

sim/graphics/view/draw_call_type (int, read-only)

For 3-d drawing callbacks, this dataref indicates the type of drawing being done for VR multi-eye rendering:

  • 1 Mono (regular) drawing is in progress
  • 3 Stereo drawing is in effect and this call is to render the left eye
  • 4 Stereo drawing is in effect and this call is to render the right eye.

When the left and right eye are dispatched, the transform stack will have been modified to take into account per-eye offsets.

sim/graphics/settings/HDR_on (int, read-only)

This boolean dataref tells whether the HDR deferred renderer is enabled.

  • 0 HDR is not enabled
  • 1 HDR is enabled

sim/graphics/settings/scattering_on (int, read-only)

This boolean dataref tells whether atmospheric scattering is enabled; since atmospheric scattering is always on in X-Plane 11, it will always have a value of 1.

Datarefs for OpenGL State and Modes

All drawing callbacks provide datarefs that provide access to the transform stack at the time your drawing callback is called.

sim/graphics/view/projection_matrix (float[16], read-only)

sim/graphics/view/modelview_matrix (float[16], read-only)

sim/graphics/view/viewport (int[4], read-only)

These three datarefs provide complete access to the modelview, projection and viewport transformations, allowing you to map between modelview and OS window coordinates.

sim/graphics/view/world_matrix (float[16], read-only)

sim/graphics/view/acf_matrix (float[16], read-only)

sim/graphics/view/projection_matrix_3d (float[16], read-only)

These three datarefs can be read during a 2-d drawing callback or window drawing callback to gain access to the transform stack that was used to render the 3-d world, if there was a 3-d render. The world matrix provides the model-view matrix for standard OpenGL world coordinates (e.g. for XPLMWorldToLocal).

The acf matrix provides a modelveiw matrix whose origin is the aircraft’s nominal CG and whose axes are aligned with the aircraft. This is equivalent to starting with the world matrix, translating to the aircraft location and rotating by the aircraft Eulers, but may provide better precision.

sim/graphics/view/is_reverse_float_z (int, read-only)

This dataref indicates whether the depth buffer for the current drawing callback is using regular linear depth encoding or reverse-float-Z conventions.

ValueDepth FormatDepth FunctionDepth Range

0GL_DEPTH_COMPONENT_24GL_LEQUAL-1..1

1GL_DEPTH_COMPONENT_32FGL_GEQUAL0..1

The depth buffer will have an attached 8 bit stencil buffer.

sim/graphics/view/is_reverse_y (int, read-only)

This dataref indicates whether the current rendering pass uses OpenGL conventions for the framebuffer (origin in lower left, Y axis points up) or DirectX/Metal Conventions (origin in upper right, Y axis points down). Even when X-Plane is running in reverse Y mode, the transform stack will be set up such that the model view matrix has the same input coordinate system, e.g. Y is up in 3-d, and Z is south.

Legacy Datarefs for Object Animation

When datarefs are read from a plugin to compute an object’s animation pose or to calculate the setup of its lights, the following datarefs are available to read to learn which object is being rendered.

sim/graphics/animation/draw_object_x (float, read-only)

sim/graphics/animation/draw_object_y (float, read-only)

sim/graphics/animation/draw_object_z (float, read-only)

sim/graphics/animation/draw_object_psi (float, read-only)

This technique for determining which object is being animated is deprecated and is made obsolete by XPLMInstancing.

1 Comment

Plugin compatibility guide for X-Plane 11.50

Starting with X-Plane 11.50, users have the ability to change the graphics API that is used by X-Plane. They now have the option to choose between OpenGL (all platforms), Vulkan (Windows and Linux) and Metal (macOS). This has potential implications for third party code that interacts with X-Plane’s rendering. The main goal with Vulkan and Metal is to deliver a more consistent and higher framerate, while also maintaining compatibility with the existing add on ecosystem as much as possible.

Compatibility with existing plugins

As a general note, existing plugins running under the OpenGL renderer in X-Plane 11.50 should behave exactly the same as in X-Plane 11.41. Assuming the plugins behaved nicely and played by the rules of the SDK, compatibility between 11.50 OpenGL and 11.41 is provided.

Whether a user selects OpenGL, Vulkan or Metal, the following kinds of operations don’t require any changes to existing add-ons:

  • Scenery add ons. All renderers support the existing scenery features and texture formats and will look the same on all platforms.
  • Plugins that don’t interact with the rendering system and instead provide additional functionality without the need to draw in the world.
  • Window drawing using the XPLM 3 SDK windows. This includes UI elements drawn using the XPWidgets library as well as custom OpenGL drawing.
  • 2D drawing callbacks. This includes UI elements drawn using the XPWidgets library as well as custom OpenGL drawing.
  • Panel drawing callbacks. This includes 2D panels as well as 3D panels drawn inside the aircraft.
  • 3D drawing using the XPLM instancing API.

Breaking changes have been made to the 3D drawing callbacks. All 3D drawing phases have been deprecated as of X-Plane 11.50 and will no longer be called under either the Vulkan or Metal renderer. Additionally, the XPLMDrawObjects() and XPLMDrawAircraft() APIs have been deprecated and also no longer works with either Vulkan or Metal. 3D drawing callbacks, XPLMDrawObjects(), and XPLMDrawAircraft() will continue to work under OpenGL in 11.50 like they did in 11.41.

X-Plane has offered an alternative to the XPLMDrawObjects() and XPLMDrawAircraft() APIs since X-Plane 11.10 in the form of the instancing API, which we highly encourage developers to adopt. While not a direct, drop in replacement, it offers much more flexibility for plugin authors and X-Plane than the previous system did. You can read the documentation for the instancing API here and check out our example code here.

OpenGL compatibility notes

When a user runs X-Plane with either Vulkan or Metal, X-Plane itself will exclusively run with the selected backend and no rendering is done using OpenGL. To provide compatibility with plugins X-Plane will create a OpenGL context that is exclusively for use by plugins. X-Plane will create minimal resources in this OpenGL context to enable support for APIs like XPLMGetTexture() and to facilitate sharing of framebuffers across Vulkan/Metal and OpenGL. Plugins should not assume the existence of any resources in an OpenGL context and should instead use public APIs to retrieve resources. No guarantee is made with regards to availability of resources in the OpenGL context across versions or even runs of X-Plane. Plugins that try to sniff resources from the OpenGL context, whether running under Vulkan, Metal or OpenGL, are considered misbehaved and no compatibility guarantees are made.

Plugins that use Vulkan/Metal compatible drawing operations don’t need to do any special processing or precautions. X-Plane provides all synchronization and resource sharing across the rendering APIs as part of its internal plugin bridge system. We expect this OpenGL plugin bridge to exist for the foreseeable future as something that plugins can be authored against. OpenGL provides an easy to use API for plugin needs without any of the complications that come with Vulkan or Metal.

Alternatives to 3D drawing

As mentioned above, the X-Plane 11.41 3D drawing phases have been deprecated in X-Plane 11.50 and are no longer called on Vulkan and Metal. This should not be a problem for most plugins, although a few might require changing to the XPLM instancing API. However, we have found that a lot of third party plugins rely on the 3D drawing phases to read datarefs or do internal bookkeeping, without actually doing any real drawing. This will no longer work under either Vulkan or Metal with 11.50 due to these drawing phases no longer being dispatched, although it is still possible under OpenGL.

We strongly recommend authors avoid doing this in general, even on OpenGL. 3D drawing phases are meant exclusively for 3D drawing, and dispatching them isn’t free in terms of CPU overhead on X-Plane’s end. Plugins that don’t require 3D drawing capability should instead use the flight loop callbacks to do all of their bookkeeping.

We also discovered that a lot of 3D drawing is actually in the form of overlays or other kinds of markers or labels on 3D objects. These can be done from a 2D drawing callback instead of a 3D drawing callback by transforming the 3D world coordinates onto the 2D screen and then using those coordinates to draw. This will work regardless of whether a user runs OpenGL, Vulkan or Metal. Example code that deals with the 3D world to 2D screen coordinate transform can be found here. Note though that this will always draw over world objects since there is no depth information available.

We expect most plugins to be able to entirely phase out their usage of the 3D drawing phases with minimal code changes necessary, either by adopting the instancing API, moving bookkeeping to the flight loop, or using a 2D drawing callback to draw overlays. We highly recommend exploring these alternatives to the previous 3D drawing approaches as they allow X-Plane to run much more efficiently.

3D drawing using the modern drawing phase

Plugins that require completely custom drawing in the X-Plane world with the ability to be occluded by other objects won’t work with the above work arounds. We don’t expect very many plugins to be in this category, with custom weather rendering plugins being the notable exception. For plugins like this, X-Plane 11.50 offers a new 3D drawing phase as part of the XPLM 302 SDK: xplm_Phase_Modern3D. For technical reasons this drawing phase is not available on Metal and only runs on Vulkan and OpenGL!

This new drawing phase has many caveats and gotchas and comes with the big fat warning that it isn’t very cheap in terms of CPU overhead. We highly discourage the use of it unless it’s absolutely necessary to perform real, custom 3D drawing! As mentioned before, the biggest caveat is that this drawing phase will not be called under Metal. Additionally there is only a single drawing phase now which conceptually sits right where the old before xplm_Phase_Airplanes draw phase used to be. The before and after phase of the modern 3D drawing phase are called directly in succession and no X-Plane rendering happens in between.

There are two additional things to watch out for when doing 3D rendering in general:

First, X-Plane can run with reverse-z semantincs. Meaning that the depth range is [0, 1] as opposed to the traditional [-1, 1] and the depth comparison is GEQUAL instead of LEQUAL. As a side effect, this means that the depth buffer is cleared to 0 instead of 1. When in reverse-z mode, the depth buffer will be in floating point format (DEPTH_32F) instead of the traditional 24bit integer format. X-Plane will set up the OpenGL state and projection matrices for you to reflect these changes when dispatching plugins, but it’s something you might want to be aware of if you do any depth buffer readbacks, set the depth state yourself, or calculate your own projection matrices. Whether X-Plan is in reverse-z mode can be observed through the sim/graphics/view/is_reverse_float_z dataref. When running under Vulkan, X-Plane will always run in reverse-z mode, when running under OpenGL it’ll only be in reverse-z mode for VR rendering.

Second, X-Plane can run with reverse-y semantics. In reverse-y mode, the colour and depth buffer are flipped along the y-axis (the origin is top left and grows downward). When running in reverse-y mode, it’s the responsibility of the plugin author to flip the front face winding to avoid polygons from getting incorrectly backface culled. The projection matrix provided by X-Plane takes care of the changed projection parameters, but if you do your own projection matrix set-up you’ll have to do this change yourself. Whether X-Plane is in reverse-y mode can be observed through the sim/graphics/view/is_reverse_y dataref. When running under Vulkan, only 3D drawing with the HDR renderer is in reverse-y mode. 2D rendering phases and OpenGL rendering are never in reverse-y mode.

6 Comments

Designing Manipulators for Virtual Reality

A manipulation is an action the user can take by clicking on your object. Manipulations can only be used in cockpit objects.

Traditionally, manipulators have been focused on the interaction between the mouse and cockpit. VR implementation has added a few new possibilities and made older processes obsolete. This guide explains manipulators in terms of how real objects move instead of in terms of mouse clicks.

The Pieces Of A Cockpit Control

There are 6 components of a cockpit control.

Required components:

  1. An interaction spot, such as a single place to click or interact in VR, or the two spots that are automatically created using something like Command Switch Up Down
  2. The manipulator type that tells X-Plane what type of interaction spot to make and what happens when you interact with it.
  3. The manipulator’s dataref or command, from X-Plane or a plugin, that changes or triggers when the interaction spot is interacted with. Also, certain other case by case parameters like cursor type, tooltip, etc
  4. The manipulator mesh, which determines where the interaction spot will be in X-Plane. It is usually blocky in shape for an easier time interacting with it

Optional components:

  1. A visual mesh for what the user sees. The manipulator mesh is made invisible (but is still interactable), while the user sees a high-detail visual mesh. This is standard for yokes, but may be more work than needed for simple buttons.
  2. Finally, the animations that keep the manipulator mesh and visual mesh (if you have any), moving in sync so it doesn’t break realism. This does not have to be the same as the manipulator dataref (if any), but very well could be.

A simple example: Making an extremely simple Push button (manipulator type) to fire commands.

  • Make a panel where the button is supposed to be (interaction spot), and give the panel the relevant manipulator information, such as the command you want to use and the cursor to see.
  • Finally, include the button in the cockpit texture so the user has something to look at.

A more complex example: Creating a slide for some trim flaps.

  • You want a linear dragging motion, and pick Drag Axis for their manipulator type.
  • Model the control, a small tapered cylindrical knob.
  • Users say this is hard to click and easy to miss (interaction spot), so you make two meshes: One a slightly oversized cylinder that the user will actually click (manipulator mesh) and a high detail tapered cylinder the user will see moving (visual mesh).
  • The manipulator changes the dataref sim/cockpit2/….trim (manipulator’s dataref).
  • Since the user drags the manipulator mesh but sees small tapered visual mesh, they must be animated the same way. For convenience, the manipulator’s dataref is used.

And so, the user drags the trim flap slider up, the trim flaps go up, the animation moves up. Note: Clamping the manipulator’s animation is possibly essential to prevent incorrect or unrealistic motion

Manipulator Types

The following names are based on the OBJ spec and the XPlane2Blender add on. The names are probably similar in whatever OBJ exporter you are using. Otherwise, see the supporting documents of that exporter or e-mail their author for more details.

Levers

MECHANISM You want For firing commands For changing DREFs
Interaction Is Consumed But Nothing happens Noop Noop
linear lever Command Axis* Drag Axis
With Detents Drag Axis With Detents
rotational lever Drag Rotate
With Detents Drag Rotate With Detents
Ball Joint Drag XY**
Yoke Drag XY***

*The command axis manipulator runs a command based on a drag in one direction and the other – this doesn’t fit well with real linear mechanisms, but in rare cases it can provide a nice user experience for a detented linear lever, like a flap handle.

** Ball joints do not work well in VR – the XY manipulator is an approximation

*** Yokes should be done via the XY manipulator – the _vrconfig.txt file has special commands

to make yokes work perfectly. See the VR configuration file format spec for details.

Details on Noop

If you want a click to be consumed before it reaches another manipulator underneath it, use a Noop. This is useful for temporarily disabling a control without the use of a plugin, such as a locked lid over an “EJECT” button. Make the glass a noop, and the button a Command. When the locked lid over and eject button has played its animation to raise, the eject button becomes clickable.

Buttons

MECHANISM CMD DREF
push-button Command Push (radio, delta, toggle, wrap)
knob Command Knob Axis Knob
knob (2-way) Command Knob 2
horizontal switch Command Switch Left Right Axis Switch Left Right
horizontal switch (2-way) Command Switch Left Right 2
vertical switch Command Switch Up Down Axis Switch Up-Down
vertical switch (2-way) Command Switch Up Down 2

Note that the command variant is always preferred in terms of quality of user experience – dataref variants are provided only to help authors with weird situations. The various push button dataref manipulators vary based on what values are written to the dataref.

The Manipulation section of the OBJ8 spec contains more information about how these type names get turned into OBJ directives and the exact details of their parameters.

Leave a comment

Improving ATC Speech and Pronunciation

The spoken phrases and names of the ATC system come from a cloud-base Text-To-Speech (TTS) engine. Several spreadsheets of vocabulary are fed to the cloud engine to be spoken and saved as individual sound files. These are then processed and saved as part of the X-Plane resources which are distributed as part of the application. While the TTS engine is very good at getting reasonable pronunciations for most things, it is by no means perfect. Regionalization and other types of specialization are often necessary to improve the accuracy of the speech.

We have made our spreadsheets public so that the community can edit them to correct mistakes that they may find. We will periodically grab the latest spreadsheets with community corrections and rebuild our internal speech resources to include the new corrected pronunciations, then make them available as part of standard X-Plane updates.

You can find the spreadsheet here.

The spreadsheet currently contains 5 tabs along the bottom for the categories: Airlines, Airports, Aircraft Makers, Aircraft Models and VORs, as well as an instructions tab. Each category tab has two common editable fields. One is what the ATC engine will display as text on screen. The other is what will be spoken as audio output.

It’s important to note that some users will disable ATC speech and just want to see textual ATC commands. Others may disable the text and only want to hear spoken commands. Because of this, the ATC engine needs data for text and speech. For example, you may want to display “B737-800” as an aircraft type in text, but you may want to say “737 800” in speech; without the ‘B’ and without pronouncing the ‘dash’. That’s why the two columns exist independently.

Speech and pronunciation can also be adjusted by using the SSML standard. Note that you do NOT need to add <speak></speak> tags. It’s implied. There are many resources available on the web to help learn SSML syntax as well as pronunciation characters. They all should work fine, independent of the TTS engine used. It is suggested that you create a free Amazon Web Services account and use the Amazon Polly Text-To-Speech synthesizer online to listen to your syntax before editing the spreadsheet. However, you can also use Google’s online synthesizer or various others.

Please do not attempt to use pronunciation to create regional accents in the spoken words as this will make things more difficult. For example, the word Boston should be “Baw-stun” even if regionally they’d say “Bah-stin”. This type of feature IS actually possible someday but it is NOT done on the pronunciation level in the spreadsheet.

21 Comments

Updating Aircraft for X-Plane 11.30

Aircraft saved in Plane Maker version 11.30 will be opted into a few new systems & requirements. Aircraft will need to be updated accordingly. If you wish to avoid updating your aircraft, do NOT re-save it in Plane Maker 11.30.

Stabilizer

Stabilizer wash was severely broken for high aspect ratio wing aircraft like fighters in older versions. This is the only exception to the re-save rule–it is fixed in 11.30 and is applied whether or not your aircraft is re-saved in 11.30. This fix was mandatory for fighter aircraft; most other planes should not see a difference.

Oxygen System

It is now possible to equip high-flying aircraft with an oxygen system rather than or in addition to the pressurized cabin, to allow realistic black-out behavior also with unpressurized aircraft. The new oxygen system is mandatory–if you do not want to use it, override the pressurization system with the new override dataref. See the article “The X-Plane oxygen system” for more information.

Lights

Lights attached to cockpit object of type glass (in or out) used to light everything. This is corrected for 11.30. If your aircraft loses interior lights upon re-save in Plane Maker 11.30, check your cockpit object’s lighting settings in Plane Maker.

Cockpit obj

The cockpit.obj is no longer a special object. It is attached to the plane in the Miscellaneous Objects screen in Plane Maker 11.30. Aircraft will be automatically upgraded upon re-save in Plane Maker 11.30. For more information, see the “Attaching 3-D Objects” section of the Plane Maker manual.

Cockpit Prefill

X-Plane 11.26 had a bug where it ignored cockpit prefill settings. 11.30 correctly handles prefill options so you will need to review your prefill settings to ensure they are set up correctly.

Autopilots

Version 11.30 offers to equip planes with preconfigured autopilots, in addition to the many configurable options of previous X-Plane versions. See the articles “X-Plane autopilot params” and “Preconfigured autopilots and other autopilot changes in 11.30” for more information.

Icing Systems

X-Plane simulates ice accumulation on your aircraft that will affect your performance greatly. X-Plane also simulates a wide variety of systems that can prevent the accumulation of ice on various surfaces (anti-ice), or get rid off ice that has accumulated (de-ice). See the article “The X-Plane Anti- and De-Ice systems” for more information.

Propeller Feathering

X-Plane simulates governors for constant speed propellers that can have various failure modes. Depending on the type of engine/propeller combination on the aircraft, the behavior of the governor in case of an engine failure will be different. X-Plane 11.30 allows you to select the type of governor to simulate, to accommodate a wide range of different engine types. See the article “Propeller feathering systems” for more information.

Vacuum Systems

X-Plane has two vacuum systems per airplane, one for the pilot side instruments and one for the copilot side instruments. By default, the suction is generated by pumps driven by the engine, so it is dependent on your engine RPM. Two additional sources of vacuum are now available in X-Plane 11.30. See the article “Vacuum systems” for more information.

Gyro systems

X-Plane can drive the attitude indicator, also known as the artificial horizon, from any of three systems. This yields a total of six gyros you can use for your attitude instruments (pilot and copilot side). See the article “Vacuum gyro limitations and caging” for more information.

Fixed turboprop engine governor

To get the correct governor type for a fixed-shaft turboprop, you need to set both the engine type and the failure mode of the prop governor correctly. Then, the prop must be configured for sensible blade angles to achieve correct alpha and beta. Correct behavior of the governor requires correct set up of the prop first. See the article “Setting up a fixed turboprop engine governor” for more information.

Default Particle Effects

By default, the particle effects from 11.26 are still enabled on all aircraft. To turn them off, go to Expert > Part Visibility in Plane Maker 11.30 and use the checkboxes in the section “Disable X-Plane’s Built-In Effects.”

Toe Braking

Previous to 11.30, automatic toe braking for users without hardware or plugin-controlled toe brakes was applied automatically to aircraft based on internal heuristics and analysis of the landing gear. The heuristics sometimes produced useful results, but sometimes not, and they weren’t easily author-controllable

Starting in X-Plane 11.30, authors can control the amount of automatic toe brake applied with rudder deflection in Plane-Maker; the field “left and right brake power” in the landing gear screen’s “Gear Data” field lets you control this feature.

A value of 0 will mean X-Plane applies no automatic toe brakes with rudder deflection; positive values apply the toe brakes based on a power curve. Use a value of 1 for linear brake application with rudder, and larger values to defer brake application to the strongest rudder deflections. Generally, if you need toe brakes, but you want less of them, use a larger number.

For older aircraft, this field will be pre-initialized to match X-Plane 11.26’s shipping behavior.

Vectored Thrust

Due to a bug, vectored thrust was applied even to engines for which the per-engine check box was not checked.  While these aircraft continue to have vectored thrust in 11.30 to maintain compatibility, you will need to correct your check-boxes when you re-save in Plane-Maker 11.30.

Todo for authors: review the engine tab and make sure the “Vectored thrust” check-box is set appropriately for all engines.

4 Comments

Vacuum gyro limitations and caging

Gyro systems

X-Plane can drive the attitude indicator, also known as the artificial horizon, from any of three systems. This yields a total of six gyros you can use for your attitude instruments (pilot and copilot side). The three systems are:

  • vacuum gyro – this one is driven by air being sucked through it, and the vacuum necessary to pull the air into it is generated by an engine-driven vacuum pump. This is the system most often found in simpler general aviation aircraft like a C172. X-Plane simulates a vacuum pump driven off the accessory section of the engine, thus the gyro will spin up when the engine spins up.
    Check out the article on the vacuum system itself for more information.
  • electric gyro – this gyro replaces the failure-prone vacuum pump, hose, and filter system with a simple electric motor inside the instrument, which spins up the gyro. You find those in non-glass Cirruses, Diamonds, and other more modern general aviation aircraft. X-Plane drives this motor off a DC electric bus, or, if checked in Plane Maker, off the AC inverter.
  • AHARS – the fully electronic attitude and heading reference system replaces the gyros with sagnac laser-gyros or cheaper MEMS gyroscopic sensors (comparable to the ones in your smartphone) to generate attitude and heading information without any moving parts. This system is obviously electrically powered.

Limitations of the mechanical attitude gyro instrument

The attitude instrument uses a gimbal mechanism which allows the instrument case (and by extension, the whole airplane) to revolve around the gyro, which keeps pointing upward. The movements of the gimbal are translated by a pickup mechanism into movements of the part of the instrument the pilot is looking at. So while the plane rotates around the gimbal, the deflection of the gimbal is what causes the blue/brown part of the attitude indicator to move. It is important to keep in mind that this pickup mechanism is quite delicate, and also limited in its freedom of movement. It can indicate up to 110 degrees in bank and 70 degrees in pitch. Beyond that, the mechanism locks up and the attitude reading on the instrument becomes inaccurate. Moreover, a violent excursion of the bank or pitch limitations of the instrument can even cause permanent damage to the pickup mechanism, but that doesn’t happen in X-Plane.
After an exceeding of the instrument limitations, the indicated pitch or bank will be off, depending on how far the gyro was forced off from its natural position. The gyro rights itself at three degrees per minute in normal flight conditions, so you will see the attitude indicator correcting itself at this slow rate. To force the gyro back into the upright position quicker, you can pull the caging or fast erect knob.

Caging to the rescue

Aerobatic planes that are expected to exceed 70 degrees of pitch and 110 degrees of bank, if equipped with an attitude indicator at all, will have an instrument that allows caging. A caged gyro is locked to the instrument case, and rather than the delicate pickup mechanism taking the beating, the whole instrument absorbs the gyroscopic forces. While it is caged, the attitude indicator indicates straight and level, while the aerobatic plane can go to extreme bank and pitch angles without damaging the gyro. Back in normal flight, the gyro can be uncaged and resume normal operation.

What is “fast erect”?

On some attitude indicators, the caging knob is instead labeled “(pull to) fast erect”. The mechanism however is the same: When pulled, the gyro is forced into the upright straight and level position and locked to the instrument case, however the fast erect knob snaps back to the uncaged position when let go, while a caging knob can be locked in the caged position. Since they perform the same operation, the knob is the same dataref

sim/cockpit/gyros/gyr_cage_ratio[N]

For a fast erect knob, the dataref can be ramped up with the command

sim/instruments/ah_fast_erect(_copilot)

this simulates pulling out the knob, which instantly springs back when let go.
For the cage knob the command

sim/instruments/ah_cage(_copilot)

instead simulates toggling the knob to the pulled position.

Comments Off on Vacuum gyro limitations and caging

Guidelines for AI aircraft airport use

Realistic AI aircraft traffic at airports requires specifying multiple parameters in the WED scenery file.

Thoughhout all version of X-Plane 11, minimum requirements for successful AI traffic operation at an airport are:

  1. The airport is of type “airport”, i.e. not a “seaport” or “heliport.”
  2. Have at least one ATC frequency of type “Tower” defined.
    1. Note this refers to the “Type” property, not the name given to the frequency entry, which has no relevance for AI operation.
  3. At least one (very preferably multiple) ramp starts of sufficient size is specified:
    1. The size of the largest ramp start (of any type) must be larger or equal to the actual AI aircraft attempting to spawn/land.
    2. X-Plane will not check if that ramp start is actually vacant or the right type – it rather gives ATC authority to make “emergency” decisions like parking a 747 on a Size A “Props” “Misc” ramp start, if none of the size F starts at that airport are available for some reason.
    3. See the “Guide to Ramp Starts” for details on ramp start fields.
    4. The airport should have at least one ramp start of type “gate/tiedown” and all starts near the runway should be of type ”misc” only. This prevents ATC accidentally spawning AI inside a runway hotzone – which creates a fatal deadlock.
  4. At least one paved runway (surface = “Asphalt” or “Concrete” only) of sufficient width and length is active.
    1. Active means either
      1. there is valid flow specification that meets the current weather condition and it includes a “Runway use” rule for that runway
      2. or no flows are specified. In this case, X-plane will auto-generate suitable flows that activate all runways under any weather condition.
    2. Sufficient width & length depends on the AI aircraft category as in the table below:
Aircraft category Min. Rwy Width Min. Rwy Length
Heavy 125 feet 10,000 feet
Fighters 125 feet 7,500 feet
Jets 100 feet 7,500 feet
Turboprops 75 feet 2,500 feet
Props 50 feet 2,500 feet
Anything else 25 feet 1,000 feet

These are all conditions to make AI spawn or attempt to land at the airport.

Note: In older documents – the “has ATC” property was noted as required for AI use. Since X-Plane 10 it is actually officially ignored – so it’s not required. Some airports may even have AI and ATC functionally without an ATC tower frequency defined in WED/apt.dat – if there is a (very rarely) used option to define ATC tower frequencies in an atc.dat file to accompany the scenery.

It also implies the actual ramp start types and ATC taxi network details do not prevent AI operation, but only help to make it look more “plausible” once AI are present at the airport. A working ATC Taxi network, either auto-generated by X-plane or specified in the scenery is required to have those AI successfully leave the runway and taxi to/from the ramp starts.

Troubleshooting Tips

To debug problems with AI operations it is recommended to start with hiding all user specified flows and ATC taxi networks in the WED scenery pack. X-Plane will then auto-generate these items, which will result in functional flows & networks, although they will also appear less polished.

By default, the X-Plane log.txt also includes information about AI spawning, flow selection and AI Taxi instructions. The art control atc/debug/log_spawn=1 prints log info on AI aircraft arrival & departure logic. Use the developer console to see this in-sim or view it in the log.txt

12 Comments

Building and Installing Plugins

Note: This article is for plugin developers. If you’re a user just trying to install a plugin, please see the “Expanding X-Plane” section of the X-Plane manual. (The exact method of installation depends on the plugin, but for many plugins, you can simply drop the plugin directory into your Resources\plugins\ directory.)


Platform Choices & Decisions

X-Plane supports plugins for all three operating systems (macOS, Windows, and Linux). This article covers issues of building and packaging plugins.

Which API to Use

There are three revisions of the X-Plane plugin API:

  • 1.0 API is supported by X-Plane 6.70 and newer.
  • 2.0 API is supported by X-Plane 9.00 and newer, is a superset of the 1.0 API
  • 2.1 API is supported by X-Plane 10.00 and newer, is a superset of the 2.0 API
  • 3.0 API is supported by X-Plane 11.10 and newer, is a superset of the 2.1 API

Plugins are almost the same for all APIs; a few exceptions for compiling and linking 2.0+ plugins will be noted.

You can use the latest SDK download to build your plugin no matter what version of the API you are targeting. By default your plugin will only be able to use 1.0 APIs and run on any version of X-Plane.

If you define the symbol XPLM200, then the 2.0 API will be available to your code, and your plugin will only work on X-Plane 9 and later.

Likewise, if you define the symbol XPLM210, you’ll have access to the 2.1 API and your plugin will only work on X-Plane 10 and newer.

Finally, if you define the symbol XPLM300, you’ll get access to the 3.0 API, and your plugin will work X-Plane 11.10 and newer.

If you’re just starting out, we recommend using the SDK 3.0 API and defining XPLM200, XPLM210, and XPLM300.

If you’re building a backward-compatible plugin (say, for both X-Plane 10 and 11), you can link against the 2.0 API and use the XPLMFindSymbol() utility to optionally fetch newer APIs. If they are not present, your plugin will receive a NULL return value and can take a fallback path.

Plugin Containers

Plugins are DLLs (dynamically linked libraries). While these have different names on different operating systems, the concept is the same: code that is linked into X-Plane while it is running. We will use the term DLL generically to mean a shared library of the appropriate type for your chosen ABI. The container types are:

  • DLLs (.dll) for Windows
  • Shared Objects (.so) for Linux
  • Shared Dynamic Libraries (.dylib) for macOS

Note that in all of these cases the plugin’s extension is .xpl, as dictated by SDK conventions, not the native platform.

Packaging Thin Plugins

A “thin” plugin is the original way of packaging plugins: the plugin consists of a single DLL with the extension .xpl, which is dropped into X-Plane’s Resources\plugins\ directory. All auxiliary files (image files, etc.) must be kept outside the plugin. Thin plugins are the only packaging supported by the 1.0 API. (Originally thin plugins were just called “plugins”.)

The obvious downsides of this are that you have to distribute a different plugin for each operating system, and you don’t get a plugin “home” directory to pack your resources.

In order to build a thin plugin, make sure your plugin ends in the extension “.xpl”.

Packaging Fat Plugins (XPLM 2.0 API)

A “fat” plugin is a folder containing one or more plugins. The plugins inside the folder have the specific names win.xpl, mac.xpl and lin.xpl. A fat plugin provides a container format that is portable across multiple operating systems; X-Plane loads only the plugin that is appropriate for the host computer and ignores the rest. The folder can also contain support files, allowing the user to install the plugin by dragging a single folder.

Fat plugins require the 2.0 API, and are the recommended way of packaging plugins that would require the 2.0 API or X-Plane 9 for other reasons.

To build a fat plugin, make sure the actual binary is inside a folder (which in turn is inside the plugins folder) and that the binary is named win.xpl for Windows, mac.xpl for OS X, or lin.xpl for Linux.

The recommended layout for a fat plugin is:

plugin folder
 mac.xpl <- mac dylib with multiple code architectures: ppc, i386, x86_64
 32
 win.xpl <- 32-bit (win32) windows dll
 lin.xpl <- 32-bit (i386) Linux shared object
 optional other 32-bit dlls needed
 64
 win.xpl <- 64-bit (x64) windows dll
 lin.xpl <- 64-bit (x86_64) Linux shared object
 optional other 64-bit dlls needed
 other files for the plugin (pngs, etc.) in any sub folders as desired.
Packaging Fat Plugins (XPLM 2.1 API)

New in X-Plane 10 are the 32-bit and 64-bit variants of fat plugins. In this case, the plugin packaging looks like this:

  • my_plugin/
    • 64/
      • mac.xpl
      • win.xpl
      • lin.xpl
    • 32/
      • mac.xpl
      • win.xpl
      • lin.xpl

(Note that you don’t need to ship both 32- and 64-bit variants of your plugins to use this packaging.)

Packaging Fat Plugins (XPLM 3.0 API)

As of X-Plane 11.10, we support one more format for packaging plugins. The downside to the 2.1 format is that all plugins are named [platform].xpl, which makes debugging tools hard, if not impossible, to use with shipping plugins. (They assume that all DLLs will have unique names, and therefore get confused if you have multiple plugins loaded that are both called, e.g., win.xpl.)

For that reason, as of XPLM 3.0, you can package plugins like this:

  • my_plugin/
    • mac_x64/
      • my_plugin.xpl
    • win_x64/
      • my_plugin.xpl
    • lin_x64/
      • my_plugin.xpl

(Note, of course, that X-Plane 11 supports only 64-bit plugins.)

Global, Aircraft, or Scenery Plugin

A “global” plugin is one that is installed in the Resources\plugins\ folder. This is the original way to install a plugin and the only one supported by the 1.0 SDK. Global plugins must be installed directly into the plugins folder (which is in turn inside the Resources folder); sub-folders are not examined.

The 2.0 API also allows plugins to be stored with aircraft; such aircraft-based plugins are loaded when the user loads the plane (not counting multi-player use of the plane) and unloads the plugin when the user picks another aircraft.

The 2.1 API also allows plugins to be stored with a scenery pack; such scenery-based plugins are loaded at startup with the global plugins, so be sure to keep resource use to zero when the user is not in your scenery area.

Only fat plugins can be stored with an aircraft or scenery pack. An aircraft plugin goes in a “plugins” folder that in turn is inside the root folder of your aircraft package. A scenery plugin goes into a “plugins” folder that in turn is inside the root folder of your scenery package.

Compiling Plugins

This section describes some of the issues when compiling plugins. This document is not meant to be substitute for the original documentation for your development tools, nor is it meant to be instructional in this regard. You should be able to use your chosen tool set to build DLLs before you begin writing plugins.

The simplest way to compile your plugins is to start with one of the examples, which come with project files and perform all the setup described below.

Recommended Compilers

We do not recommend any particular compiler, but there are more SDK-related resources available for the compilers used to produce the basic examples. Those compilers are:

  • macOS: LLVM (via Xcode)
  • Windows: Visual Studio 2010 Express or Visual Studio 2015
  • Linux: GCC 4.x

The sample code provides templates that support these compilers. One way to get started is to download a sample and then replace the code while keeping the project.

Setting Up Defined Macros

In order to use the X-Plane SDK headers, you must pre-define some macros before including any SDK headers. This is usually done by setting up the definitions (a.k.a. preprocessor macros) in your compiler settings. Most compilers accept the command-line option -D<symbol>=<value>; Xcode and Visual Studio both have project settings to predefine symbols, and in both cases they result in -D command-line options being sent to the compiler.

You must define one of the macros APL, IBM, or LIN to 1, depending on the OS you are compiling for. If no platform is defined, you will get a “platform not defined” compile error as soon as you include any SDK headers. Typically you would define the platform in the project settings or make file for each platform, so that the code can be shared between all three without modification.

Macros for the 2.0 and newer SDK APIs

In order to use the 2.0 APIs, you’ll need to define the symbol XPLM200. To the the 2.1 APIs, you’ll need to also define XPLM210, and for the 3.0 APIs, you’ll need to define all three of XPLM200, XPLM210, and XPLM300.

(This feature is designed to let you build plugins that link against old versions of the SDK from the same SDK headers. If newer symbols are not defined, you cannot accidentally use a newer routine.)

Including the SDK Headers

To use X-Plane SDK functionality, you must include the SDK headers, like this:

#include <XPLMProcessing.h>

In order for this to work, you must tell your compiler where to locate the header files. You must first decide where to install the header files. There are two basic choices:

  • If you work on your projects by yourself, you can pick one location on your hard drive to place the SDK and use it for all of your projects. The advantage is you will only have one copy of the SDK to update in the future.
  • If you share your projects with other developers, it is important that the SDK location be the same for all developers, and be located relative to the project. (Otherwise all developers would need the same hard drive name.) In this case, it makes sense to copy the SDK headers and libraries into the source tree of each project.

Once you have decided on an install location, you must provide your installer with an include path that tells it where the headers are. For example,

-IXPSDK/CHeaders/XPLM
-IXPSDK/CHeaders/XPWidgets

Most compilers require one include path for each directory to be searched.

OpenGL Considerations

OpenGL is not part of the SDK, but it is the main API for drawing from plugins, so you will almost certainly need it to create any kind of custom graphics. OpenGL deployment varies a bit by platform.

On macOS, OpenGL is a framework, and it is always available. Using OpenGL requires two steps:

  1. Add the framework to your project in Xcode (or use -framework OpenGL on the command line).
  2. Include the headers like this:
#include <OpenGL/gl.h>

For Windows and Linux, include OpenGL like this:

#include <GL/gl.h>

On Linux, you may have to first install a package, e.g.:

sudo apt-get install freeglut3-dev

(Specific instructions for your distro may vary.)

DLL Attach Functions for Windows

Windows requires a “DLLMain” function to be included in your code. It is essentially boilerplate, and typically doesn’t have to do any useful work. Here is a sample DLLMain function:

#if IBM
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
 DWORD ul_reason_for_call,
 LPVOID lpReserved
 )
{
 switch (ul_reason_for_call)
 {
 case DLL_PROCESS_ATTACH:
 case DLL_THREAD_ATTACH:
 case DLL_THREAD_DETACH:
 case DLL_PROCESS_DETACH:
 break;
 }
 return TRUE;
}
#endif

Symbol Visibility (GCC4 or higher)

For GCC-based environments (command-line Linux), the default behavior is to export all non-static C functions out of your plugin. This is not what you want, and can cause serious compatibility problems for 32-bit plugins. To get around this, use

-fvisibility=hidden

on your compiling command line.

The macro PLUGIN_API (defined by XPLMDefs.h) automatically marks a symbol as exported, so yo can do this:

PLUGIN_API void XPluginStop() { /* ... */ }

and your plugin will work correctly.

Linking Plugins

Linking is the process of taking your compiled code and making an actual DLL file on disk that is your plugin.

Linking on Windows

You will need to link against XPLM.lib, found in the SDK under SDK/Libraries/Win. Link against:

  • 32bit plugins: XPWidgets.lib, XPLM.lib
  • 64bit plugins: XPWidgets_64.lib, XPLM_64.lib

If you are using OpenGL, you’ll also want to link against OpenGL32.lib.

We recommend you set all MSVC settings to avoid depending on external DLLs other than the CRT runtime; these DLLs may not be present on destination machines, and can cause your plugin load to fail. Linking the CRT runtime statically however will cause problems for users who have a lot of plugins installed and run out of TLS slots when loading plugins.

  • C++ Code Generation: set the runtime to “multi-threaded DLL”, not “multi-threaded.”
  • General: do not use common language runtime support or MFC.

Linking on macOS

You will need to add XPLM.framework and XPWidgets.framework from the SDK to your plugin; you may also need to add the system frameworks OpenGL and possibly System or CoreFoundation to your plugin depending on what Mac settings you use.

Do not use the options “-undefined_warning” or “-flat_namespace” – these are no longer needed and not recommended.

 

Linking on Linux

There are no link libraries on Linux for the SDK; instead pass the command-line option

-shared -rdynamic -nodefaultlibs -undefined_warning

to the linker. This will let you link despite not having XPLM symbols defined. To include libraries like OpenGL use this:

-lGL -lGLU

Finally, you may need to use a linker-script for your 32-bit plugin to avoid symbol collisions. To do this, create a file like this:

{
 global:
 XPluginStart;
 XPluginStop;
 XPluginEnable;
 XPluginDisable;
 XPluginReceiveMessage;
 local:
 *;
};

and then refer to it on the command line like this:

-Wl,--version-script=<text file>
Comments Off on Building and Installing Plugins