Generic protocol: Difference between revisions
(http://www.mail-archive.com/flightgear-devel@flightgear.org/msg32560.html) |
|||
Line 165: | Line 165: | ||
</PropertyList> | </PropertyList> | ||
===Writing data in XML format | ===Writing data in XML format=== | ||
Assuming the file is called [[$FG ROOT]]/Protocol/xmltest.xml, then it could be used as | Assuming the file is called [[$FG ROOT]]/Protocol/xmltest.xml, then it could be used as | ||
fgfs --generic=file,out,1,/tmp/data.xml,xmltest | fgfs --generic=file,out,1,/tmp/data.xml,xmltest | ||
Line 190: | Line 190: | ||
</chunk> | </chunk> | ||
For more examples, see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg37892.html]. | |||
<chunk> | <chunk> | ||
<node>/velocities/airspeed-kt</node> | <node>/velocities/airspeed-kt</node> | ||
Line 202: | Line 203: | ||
</generic> | </generic> | ||
</PropertyList> | </PropertyList> | ||
== Analyzing the resulting binary packet format == | == Analyzing the resulting binary packet format == |
Revision as of 19:36, 26 March 2013
The generic communication protocol for FlightGear provides a powerful way of adding a simple ASCII based or binary input/output protocol, just by defining an XML encoded configuration file and placing it in the $FG ROOT/Protocol/ directory.
The generic protocol can be easily set up for both input and output. And it supports not just a single medium, but can be easily made to use files, FIFOs, sockets etc. The generic protocol is really good for things like exporting to a delimited ascii file for import into excel for instance.
XML File Layout
A protocol file can contain either or both of <input> and <output> definition blocks. Which one is used depends on how the protocol is called. The following example would only use the <output> definitions block.
--generic=file,out,1,/tmp/data.xml,myproto
If you're using a serial port under Windows, you must use a special escape sequence for COM port numbers higher than COM9.
Ex: --generic=\\.\COM10,out,1,/tmp/data.xml,myproto
More detail can be found in this Microsoft KB article: http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85%29.aspx
Overview of the XML file
<?xml version="1.0"?> <PropertyList> <generic> <output> <binary_mode>false</binary_mode> <line_separator></line_separator> <var_separator></var_separator> <preamble></preamble> <postamble></postamble> <chunk> ... first chunk spec ... </chunk> <chunk> ... another chunk etc. ... </chunk> </output> <input> <line_separator></line_separator> <var_separator></var_separator> <chunk> ... chunk spec ... </chunk> </input> </generic> </PropertyList>
Input/Output Parameters
Both <input> and <input> blocks can contain information about the data mode (ascii/binary) and about separators between fields and data sets, as well as a list of <chunk>s. Each <chunk> defines a property that should be written (and how), or a variable and which property it should be written to.
ASCII protocol parameters
Output only:
<preamble> STRING default: "" file header put on top of the file <postamble> STRING default: "" file footer put at the end of the file
Input & Output:
<binary_mode> BOOL default: false (= ASCII mode) <var_separator> STRING default: "" field separator <line_separator> STRING default: "" separator between data sets
- <var_separator> is put between every two output properties
- <line_separator> is put at the end of each data set.
Both can contain arbitrary strings or one of the following keywords:
Name Character ------------------------------ newline '\n' tab '\t' formfeed '\f' carriagereturn '\r' verticaltab '\v'
Typical use could be:
<var_separator>tab</var_separator> <line_separator>newline</var_separator>
or
<var_separator>\t</var_separator> <line_separator>\r\n</line_separator>
Binary protocol parameters
To enable binary mode, simply include a <binary_mode>true</binary_mode> tag in your XML file. The format of the binary output is tightly packed, with 1 byte for bool, 4 bytes for int, and 8 bytes for double. At this time, strings are not supported. A configurable footer at the end of each "line" or packet of binary output can be added using the <binary_footer> tag. Options include the length of the packet, a magic number to simplify decoding. Examples:
<binary_footer>magic,0x12345678</binary_footer> <binary_footer>length</binary_footer> <binary_footer>none</binary_footer>
Variable Parameters - <chunk> spec
Both <input> and <output> block can contain a list of <chunk> specs, each of which describes the properties of on variable to write/read.
<name>
For ease of use and not tranferred (like a notes tag)
<node>
The property tree node which provides the data
<type>
The value type which is needed for formatting, one of string, float, bool, int (default: int). Its recommended that this tag is present otherwise spurious results can occur.
<format>
ASCII protocol only, not used or needed in binary mode. Defines the actual piece of text which should be sent. it can include "printf" style formatting options like:
<type> %s string %d integer (default) %f float
<factor>
An optional multiplication factor which can be used for unit conversion, for example, radians to degrees.
<offset>
An optional offset which can be used for unit conversion, for example, degrees Celcius to degrees Fahrenheit.
<format>
Chunks can also consist of a single constant <format>, like in:
<format>Data Section</format>
Examples
Example 1
Writes log of this form:
V=16 H=3.590505 P=3.59 V=12 H=3.589020 P=3.59
<?xml version="1.0"?> <PropertyList> <generic> <output> <line_separator>newline</line_separator> <var_separator>newline</var_separator> <binary_mode>false</binary_mode> <chunk> <name>speed</name> <format>V=%d</format> <node>/velocities/airspeed-kt</node> </chunk> <chunk> <name>heading (rad)</name> <format>H=%.6f</format> <type>float</type> <node>/orientation/heading-deg</node> <factor>0.0174532925199433</factor> </chunk> <chunk> <name>pitch angle (deg)</name> <format>P=%03.2f</format> <node>/orientation/pitch-deg</node> </chunk> </output> </generic> </PropertyList>
Writing data in XML format
Assuming the file is called $FG ROOT/Protocol/xmltest.xml, then it could be used as
fgfs --generic=file,out,1,/tmp/data.xml,xmltest
<?xml version="1.0"?> <PropertyList> <generic> <output> <binary_mode>false</binary_mode> <var_separator>\n</var_separator> <line_separator>\n</line_separator> <preamble><?xml version="1.0"?>\n\n<data>\n</preamble> <postamble></data>\n</postamble> <chunk> <format>\t<set></format> </chunk> <chunk> <node>/position/altitude-ft</node> <type>float</type> <format>\t\t<altitude-ft>%.8f</altitude-ft></format> </chunk>
For more examples, see [1].
<chunk> <node>/velocities/airspeed-kt</node> <type>float</type> <format>\t\t<airspeed-kt>%.8f</airspeed-kt></format> </chunk> <chunk> <format>\t</set></format> </chunk> </output> </generic> </PropertyList>
Analyzing the resulting binary packet format
A utility called generic-protocol-analyse can be found under FlightGear/utils/xmlgrep which can be used to analyze the resulting data packet for the binary protocol. The output would be something like:
bintest.xml Generic binary output protocol packet description: pos | size | type | factor | description -----|------|--------|------------|------------------------ 0 | 4 | int | | indicated speed (kt) 4 | 4 | float | | pitch att (deg) 8 | 4 | float | | magnetic heading (deg) 12 | 4 | int | | outside air temperarure (degF) 16 | 1 | bool | | autocoord total package size: 17 bytes
Generic Protocol
FlightGear has an inbuilt "generic" protocol to push and pull data. (todo)
To interface with FlightGear on a socket for example, the following steps need to be taken.
- Establish which "properties" you want to appear "on the wire"
- Create a my_protocol.xml file containing those properties
- Start flight gear on a socket using my_protocol.
For this simple example say were interested in heading and altitude, and we want to "listen" ie output to a socket at port 6789, udp and receiving 10 times a second in the format:
alt\thead\n // ie altitude - tab - heading - newline
The first step is establishing the nodes, in this example
/position/altitude-agl-ft eg (22.4713923) /orientation/heading-deg eg (297.966325)
Next create a file my_protocol.xml. This needs to be located at
$FG_ROOT/Protocol/my_protocol.xml
The XML looks like this:
<?xml version="1.0"?> <PropertyList> <generic> <output> <line_separator>newline</line_separator> <var_separator>tab</var_separator> <chunk> <node>/position/altitude-agl-ft</node> <name>altitude to go</name> <type>float</type> <format>%03.2f</format> </chunk> <chunk> <node>/orientation/heading-deg</node> <name>Heading</name> <type>float</type> <format>%03.3f</format> </chunk> </output> </generic> </PropertyList>
- The output tag indicates the protocol for output. The same "protocol" file can contain an "input" section, absent in this example (more later).
- line_seperator - the end of line (todo ? is this \r\n??)
- var_seperator - the delimiter for the properties, this could be "|", "###", any string.
- The two chunk blocks contain our data. Note that these appear in the order presented within the xml file.
- node - the node of data we want
- name - it there for a reference, its not transmitted and note necessary (like a note)
- type - the way this xml is to interpret the value. This is quite important tag. For example if its not there or a string, then "floats" go wild and end up being a string of 32 characters with two decimal places!
- format - same syntax as printf
- There's more that can be done {todo - link to a full blown example/reference}
We can now start FlightGear and listen with:
fgfs --generic=socket,out,10,localhost,6789,udp,my_protocol
[todo] - link here to the tutorial