Display additional planes controlled by network messages.
These network message are to be generated by a 3rd party tool like a traffic generator
or a script feeding pre-recorded data. Examples are provided in the script
folder.
The supported network message formats are explained below in the Network Message Formats sections.
The project is based on
XPPlanes can be build
CMake
/ninja
,Please refer to XPMP2’s Build documentation on GitHub for details; it is the same build process as for XPMP2-Sample.
XPMP2 is included as a submodule, so clone with --recurse-submodules
option.
The project is prepared to be built with FMOD sound support. See here how to build with sound support.
This works on Mac and probably on Linux:
git clone --recurse-submodules https://github.com/TwinFan/XPPlanes
cd XPPlanes
mkdir build
cd build
cmake -G "Ninja" ..
ninja
Result are in build/mac_x64
resp. build/lin_x64
.
See Doxygen-generated code documentation.
The plugin itself is to be placed under <X-Plane>/Resources/plugins/
as usual with the following folder structure:
.../XPPlanes/
mac_x64/XPPlanes.xpl
lin_x64/XPPlanes.xpl
win_x64/XPPlanes.xpl
Resources/...
The Resources
folder needs to hold the CSL model installation, similar to LiveTraffic or XPMP2 Remote Client.
Alternatively, if you have a CSL installation somewhere, you can create a symbolic link to an existing Resources
folder. Even Windows supports symbolic links for folders by the mklink /D
command, Linux and Mac users will know the ln -s
command already (or will find help on the net).
Currently, there is no user interface available for configuring the plugin. But the plugin writes a configuration file, if there was none during startup, that you can modify. It will be read during next plugin start only, though. Find the config file in
<X-Plane>/Output/preferences/XPPlanes.prf
It includes the following config entries:
Item | Description |
---|---|
LogLevel 0 | Logging level: 0 - Debug (most output) … 4 - Fatal (least output) |
LogModelMatch 0 | Log model matching? |
ObjReplDataRefs 1 | Replace dataRefs in CSL models? (more details) |
ObjReplTextures 1 | Replace textures in CSL models? (more details) |
TCAS_Control 1 | Acquire control over TCAS/AI planes upon startup? |
PlanesBufferPeriod 5 | Buffering period in seconds |
PlanesGracePeriod 30 | Seconds after which a plane without fresh data is removed |
PlanesClampAll 0 | Enforce clamping of all planes above ground? |
PlanesHideOwnship 3 | Filters out incoming ownship data, see below |
LabelsDraw 1 | Draw plane labels |
LabelsMaxDist 5556 | Max distance in meter to draw labels |
LabelsCutMaxVisible 1 | Don’t draw labels for planes father away than visibility |
MapEnable 1 | Support display of planes in X-Plane’s map? |
MapLabels 1 | Add labels to planes in X-Plane’s map? |
NetMCGroup 239.255.1.1 | Multicast group the plugin listens to for flight data |
NetMCPort 49900 | UDP Multicast port the plugin listens to for flight data, 0 switches off |
NetBcstPort 49800 | UDP Broadcast port the plugin listens to for flight data, 0 switches off, e.g. 49005 would listen to RealTraffic’s RTTFC data |
NetTTL 8 | Time-to-live of network multicast messages |
NetBufSize 8192 | (Max) network buffer size in bytes |
Traffic simulations may include ownship data, ie. positional information of the user’s plane. If such data is fed back through the simulaton to XPPlanes, then the actual user plane would be overlaid by a plane driven by XPPlanes. To avoid that duplication, XPPlanes by default filters ownship data from the incoming data stream.
Incoming data can be compared with two values in X-Plane to identify the data
as ownship data. The bit-mask of the configuration key PlanesHideOwnship
defines, which of the comparisons shall be performed:
PlanesHideOwnship |
XP dataref | XPPlanes data field | Comment |
---|---|---|---|
0 | No filtering takes place. | ||
1 | sim/aircraft/view/acf_modeS_id |
id |
Incoming ADS-B hex id is compared to a random id XP assigns upon loading a user plane. |
2 | sim/aircraft/view/acf_tailnum |
ident/reg |
Incoming Registration is compared to the user plane’s tail number, which is part of the plane definition (PlaneMaker: Aircraft Author window) |
3 | both | both | Both: If either comparison matches incoming data is ignored. |
XPPlanes processes traffic data that is received from UDP network datagrams.
XPPlanes can listen to one UDP multicast port, one UDP broadcast port, or both at the same time.
XPPlanes processes traffic data from incoming network messages on either port. The format is determined from the message content, ie. is not derived from aspects like the port number. (So you could even mix formats in different messages…)
Each traffic data record adds position information for one plane. There is no expectation as to how often updates are received. There is no need to update all planes in one go at the same time; depending on your feeding application it may be more reasonable to send updates based on individual assessment (like more frequently for turning or fast moving planes, less often for stationary planes).
Each traffic data record must include a numeric identifier for the plane it represents, and position information. Everything else is optional.
Not provided data will not change. E.g., if you want to extend the gear you can send
gear = 1.0
at the time of gear extension, then you could leave out this attribute until you want
to retract the gear, at which point your send gear = 0.0
.
Mass, wing span and area, as well as lift are used for wake turbulence configuration.
If not provided, then the XPMP2 library provides defaults,
which base on the wake turbulence category (WTC: L
, M
, H
, …)
which in turn is derived from the ICAO aircraft type designator of the plane. The defaults per WTC base on the following aircraft types:
It is recommended to include timestamp information with the tracking data,
but this is not mandatory. Without timestamp information the data is assumed to be valid now (identical to a relative timestamp of 0.0
).
Timestamp information can be relative (recommended) or absolute:
-1.2
defines the data was valid 1.2 seconds ago,
0.7
says the data becomes valid in 0.7 seconds time.In all cases will the PlanesBufferPeriod
(see Configuration) be added
to the received timestamp information and hence will delay display of the plane at the
given position. There is no restriction on the value of PlanesBufferPeriod
, it can even be 0
.
Typically, PlanesBufferPeriod
is positive,
which is useful if your traffic data is always a few seconds old,
like if you would relay real-world traffic data: If you compensate the age of the data
with the buffering period, then XPPlanes can still properly interpolate between two given
positions and planes will fly nicely. Would you run with PlanesBufferPeriod = 0
then
XPPlanes would always only see outdated data and would need to extrapolate positions
beyond the last received position, which tends to be inaccurate.
PlanesBufferPeriod = 0
is only recommended if you can feed high-speed data
(like updates every one or two seconds) with current positions.
Planes, for which the youngest timestamp is older than PlanesGracePeriod
seconds,
will be removed.
XPPTraffic
is a custom purpose-built JSON format that supports all
features of XPPlanes. One traffic data record looks like this
(see file docs/XPPTraffic.json
):
{
"id" : 4711,
"ident" : {
"airline" : "DLH",
"reg" : "D-EVEL",
"call" : "DLH1234",
"label" : "Test Flight"
},
"type" : {
"icao" : "C172",
"wingSpan" : 11.1,
"wingArea" : 16.2
},
"position" : {
"lat" : 51.406292,
"lon" : 6.939847,
"alt_geo" : 407,
"gnd" : true,
"timestamp" : -0.7
},
"attitude" : {
"roll" : -0.2,
"heading" : 42,
"pitch" : 0.1
},
"config" : {
"mass" : 1037.6,
"lift" : 10178.86,
"gear" : 1,
"noseWheel" : -2.5,
"flaps" : 0.5,
"spoiler" : 0,
"reversers" : 0,
"thrust" : 0.8,
"engineRpm" : 2000,
"visible" : true
},
"light" : {
"taxi" : true,
"landing" : false,
"beacon" : true,
"strobe" : false,
"nav" : true
}
}
Field | Description |
---|---|
id | Mandatory numeric identification of the plane. Can be a numeric integer value like 4711 or a string value. A string value is interpreted as a hex number, like "00c01abc" . |
` ` | ` ` |
ident/ | Optional object with plane identifiers, recommended to be sent at least with the first record, but can be updated any time |
/airline | String used as operator code in CSL model matching |
/reg | String used as special livery in CSL model matching |
/call | String used for computing a default label |
/label | String directly determining the label |
` ` | ` ` |
type/ | Optional object with plane type information, recommended to be sent at least with the first record, but can be updated any time |
/icao | ICAO aircraft type designator used in CSL model matching, defaults to A320 |
/wingSpan | Wing span in meters, used for wake turbulence configuration |
/wingArea | Wing area in square meters, used for wake turbulence configuration |
` ` | ` ` |
position/ | Mandatory object with position information |
/lat | latitude, float with decimal coordinates |
/lon | longitude, float with decimal coordinates |
/alt_geo | geometric altitude in feet, integer, optional/ignored if gnd = true . |
/gnd | boolean value stating if plane is on the ground, optional, defaults to false |
` ` | Means: Either gnd = true or alt_geo is required. |
/timestamp | timestamp, either a float with a relative timestamp in seconds, a float with a Unix epoch timestamp including decimals, or an integer with a Java epoch timestamp (ie. a Unix epoch timestamp in milliseconds). See section Timestamp for more details. |
` ` | ` ` |
attitude/ | Optional object with plane attitude information |
/roll | roll in degrees, float, negative is left |
/heading | heading in degrees, integer 0 .. 359 |
/pitch | pitch in degrees, float, negative is down |
` ` | ` ` |
config/ | Optional object with plane configuration data (unlike type/ this is data which is likely to change throughout a flight) |
/mass | mass of the plane in kg , used for wake turbulence configuration |
/lift | current lift in Newton, optional, defaults to mass * earth gravity , used for wake turbulence configuration |
/gear | gear extension, float 0.0 .. 1.0 with 1.0 fully extended |
/noseWheel | direction of nose wheel in degrees, float, negative is left, 0.0 straight ahead |
/flaps | flap extension, float 0.0 .. 1.0 with 1.0 fully extended |
/spoiler | spoiler extension, float 0.0 .. 1.0 with 1.0 fully extended |
/reversers | deployment of reversers, float 0.0 .. 1.0 with 1.0 fully deployed |
/thrust | thrust, float 0.0 .. 1.0 , with 1.0 full thrust, passed through to CSL models |
/engineRpm | revolutions per minute of engine, rotor, props; used to calculate angular positions and make them turn |
/visible | Boolean: Shall the plane be drawn? |
` ` | ` ` |
light/ | Optional object with a set of boolean values for the plane’s lights |
/taxi | taxi light |
/landing | landing lights |
/beacon | beacon light |
/strobe | strobe lights |
/nav | navigation lights |
Traffic data recods can be sent individually, but to make better use of the network message
several records can also be put into a JSON array. You are esponsible for ensuring that the
total message doesn’t exceed network buffers.
8192 bytes is typically safe, see NetBufSize
config options.
A proper array message starts directly with [
as root element like this:
[
{ "id" : 4711, ... },
{ "id" : "001c0abc", ... },
{ "id" : 1234, ...}
]
See docs/XPPTraffic_Array.json
for an example.
RTTFC
is a comparibly simple CSV-style format defined by RealTraffic.
See docs/RTTFC.csv
for an example.
See RealTraffic’s documentation for details, section “RTTFC/RTDEST format”.
LiveTraffic’s SendTraffic.py
script
can send such data to any UDP port, ie. also to the port defined for XPPlanes in NetBcstPort
.
RTTFC
does not include fields for configuration or light information and also misses other
attributes like pitch or any attributes required for detailed wake turbulence configuration.
If you own a RealTraffic licence,
then you could define NetBcstPort 49005
in the configuration,
run the RealTraffic app in Spotter mode, and have those planes displayed with XPPlanes directly.
(This displays RealTraffic data pretty much diretly,
ie. all differences to how the same data would look like displayed with LiveTraffic
are due to all the optimizations included in
LiveTraffic.)