The UAVTalk Protocol
The UAVTalk protocol implements the low level communication between the GCS and the autopilot. It simply provides the transport of the data structures defined by the UAVObjects. To make the addition of UAVObjects easier, the UAVTalk protocol does not need to know the details of the data structure as this is handled by the UAVObject instead. UAVTalk is only responsible of sending byte arrays and routing received byte arrays to the correct object for unpacking.
|Message part||Field||Length (bytes)||Value|
Lower nibble means the kind of message:
- 0x0 Object Data (OBJ)
- 0x1 Object request (OBJ_REQ)
- 0x2 Object with acknowledge request (OBJ_ACK)
- 0x3 Acknowledge (ACK)
- 0x4 Negative-Acknowledge (NACK)
Higher nibble has the following meaning
- bits 5-7 Protocol version ( current version is 2, 0x20)
- bit 8 (0x80) indicates a timestamped message.
Not needed since object ID predicts this but needed for blind parsing.
Length of header and data, not checksum.
|Object ID||4||Unique object ID (generated by parser, also used for framing and version control)|
|Instance ID||2||Unique object instance ID. Always 0 for single instance UAVObjects|
(only if Message Type && 0x80)
|2||Timestamp for timestamped objects (not handled by GCS)|
|Data||Data||0-255||Serialized (packed) object. The length of data is inherent knowledge about that particular object's size as identified by ObjectID. Be aware that before serializing the object, the parser sorts the fields according to length.|
|Checksum||Checksum||1||CRC-8 checksum (Header and Data)|
There are currently a total of three different type of transactions, each one is described below.
The data field is packed with values stored as little endian. This is consistent with x86, and ARM in the default little endian mode, but requires translation for big endian processors.
Bits 7 to 4 of the message type field are used to indicate the UAVTalk version used in the message. Packets with unrecognized protocol versions should be ignored.
The object message is a simple one way update of an object. Once this message is received the unpack function of the corresponding object is invoked and the object fields are updated. No response is sent on OBJ messages and they are typically used on periodic updates (see below).
Object Request Message
Object requests are sent whenever the latest value of an object is required by the sender. The OBJ_REQ message has no payload (length field is 10 / 0x0a00) and the recipient immediately responds by packing the object data and sending an OBJ message.
In case the ObjectID requested is not found, the receiver will answer with a OBJ_NACK message, instead of the OBJ message (see description of OBJ_NACK below).
Acknowledged Object Message
The OBJ_ACK message is similar to a regular OBJ message but this time an acknowledgment is sent back to the sender to confirm that the object was received by the remote end. The acknowledgement is in the form of an ACK message with no payload.
Negative-Acknowledged Object Message
OBJ_NACK is a message with no payload.
OBJ_NACK is sent in response to a OBJ_REQ message, whenever the requested ObjectID does not exist on the remote side. The non-existent requested objectID is sent back with the OBJ_NACK so that the sender can take into account the absence of this ObjectID on the remote side, and act accordingly.
The object ID is a unique 32-bit integer identifying the object the message data represent. The UAVTalk layer routes all received payloads to the appropriate object for unpacking. The object ID is automatically generated by the parser by applying a hash on the XML definition of the object. This has two advantages, first the ID is unique (very small probability of collision exists but it is insignificant) so there is no need for a centralized database of IDs, objects can be added without worrying about choosing a unique ID. Second each time the object definition is changed the ID will also change, this is a convenient way to make sure that UAVObjects on the GCS and autopilot have the same definition (i.e. have the same version).
The message type and object ID fields (first 5 bytes) also serve as framing bytes and used to detect the start of a packet. There are only a very small set of values out of all possible combinations of the first 5 bytes that are used for actual messages. In other words, the probability that the first five bytes randomly form a valid object header is very small and therefore they can be used for framing.
The UAVTalk layer is also responsible for periodic object updates. Each registered object has a timer associated with it, when the timer expires an OBJ message is sent. The timer values can be dynamically updated.
Following message exchange examples are not yet up to date to latest changes in UAVTalk. While the sequences are fine, some details on the message are not correct (i.e. Instance id that is no more optional)
Object metadata can be requested and sent by using the ObjectId +1. The metadata object has the same format as a normal object with instance 0 and the metadata fields in the following format:
|Field||Field length (bit)||Flag details||Flag Length (bit)||Value|
|access||1||Defines the access level for the local transactions (readonly=0 and readwrite=1)|
|gcsAccess||1||Defines the access level for the local GCS transactions (readonly=0 and readwrite=1), not used in the flight s/w|
|telemetryAcked||1||Defines if an ack is required for the transactions of this object (1:acked, 0:not acked)|
|gcsTelemetryAcked||1||Defines if an ack is required for the transactions of this object (1:acked, 0:not acked)|
|telemetryUpdateMode||2||Update mode used by the telemetry module (UAVObjUpdateMode)|
|gcsTelemetryUpdateMode||2||Update mode used by the GCS (UAVObjUpdateMode)|
|LoggingUpdateMode||2||Update mode used by the logging module (UAVObjUpdateMode)|
|16||Defines flags for update and logging modes and whether an update should be ACK'd (bits defined above)|
|16||Update period used by the GCS (only if telemetry mode is PERIODIC)|
|16||Update period used by the logging module (only if logging mode is PERIODIC)|
UPDATEMODE_MANUAL = 0, /** Manually update object, by calling the updated() function */
UPDATEMODE_PERIODIC = 1, /** Automatically update object at periodic intervals */
UPDATEMODE_ONCHANGE = 2, /** Only update object when its data changes */
UPDATEMODE_THROTTLED = 3 /** Object is updated on change, but not more often than the interval time */