Example Packet (Heartbeat)
packet length = 17 (6 bytes header + 9 bytes payload + 2 bytes checksum)
hdr len seq sys cmp id payload (len 9)------------------ crc---
0 1 2 3 4 5 6 7 8 9 a b c d e f 10
FE 09 4E 01 01 00 00 00 00 00 02 03 51 04 03 1C 7F
Fixed Header (6 octets)
0. packet header, always 0xFE
1. message length (9)
2. sequence number -- rolls around from 255 to 0 (0x4e, previous was 0x4d)
3. source system - what system is sending this message (1)
4. source component - what component of the system is sending the message (1)
5. message ID (0 = heartbeat)
Variable Sized Payload (specified in octet 1, range 0..255)
06-0e. payload
Packet Checksum
0f-10. CRC25
In common use (single aircraft, single autopilot), source component and systems will be (1,1)
Example Command and Payload
Command (octet 5) = 0, Heartbeat
Parms (octets 06-0e):
06-09. custom_mode = 00
0a. mav type = 2 (quadrotor)
0b. autopilot = 3 (ardupilot mega)
0c. base_mode = 0x51 = 0b01010001 (manual input, stabilized, custom mode)
0d. system_status = 4 (active, motors engaged)
0e. self.mavlink_version = 3
The parameter ordering can be confusing if you look at the XML specification, since for efficiency the parameters are not sent in the order they are listed, but are reordered as specified here.
type uint8_t Type of the MAV
autopilot uint8_t Autopilot type / class
base_mode uint8_t System mode bitfield
custom_mode uint32_t Autopilot-specific bitfield
system_status uint8_t System status flag
mavlink_version uint8_t_mavlink_version MAVLink version
(update: I didn't find this page which covers this material)
Checksum
The last two octets are the packet checksum. The first octet of the packet (the 0xFE header) is not included in the checksum.
In addition, a magic character based on the message type is included in the checksum.After the packet (less the header) has been shifted through the CRC accumulator, shift the one-byte magic number through the CRC accumulator to get the final checksum for the packet. I'll put a pointer to some sample code once I get it uploaded (update: here). It can be generated from the MAVLink package, or you can just grab the the MAVLINK_MESSAGE_CRCS from the sample code.
Tridge explains the seed value in a forum comment.
(tl;dr: it catches when people are using incompatible MAVLink XML files.)
(toc: MAVLink)
1. message length (9)
2. sequence number -- rolls around from 255 to 0 (0x4e, previous was 0x4d)
3. source system - what system is sending this message (1)
4. source component - what component of the system is sending the message (1)
5. message ID (0 = heartbeat)
Variable Sized Payload (specified in octet 1, range 0..255)
06-0e. payload
Packet Checksum
0f-10. CRC25
In common use (single aircraft, single autopilot), source component and systems will be (1,1)
Example Command and Payload
Command (octet 5) = 0, Heartbeat
Parms (octets 06-0e):
06-09. custom_mode = 00
0a. mav type = 2 (quadrotor)
0b. autopilot = 3 (ardupilot mega)
0c. base_mode = 0x51 = 0b01010001 (manual input, stabilized, custom mode)
0d. system_status = 4 (active, motors engaged)
0e. self.mavlink_version = 3
The parameter ordering can be confusing if you look at the XML specification, since for efficiency the parameters are not sent in the order they are listed, but are reordered as specified here.
type uint8_t Type of the MAV
autopilot uint8_t Autopilot type / class
base_mode uint8_t System mode bitfield
custom_mode uint32_t Autopilot-specific bitfield
system_status uint8_t System status flag
mavlink_version uint8_t_mavlink_version MAVLink version
(update: I didn't find this page which covers this material)
Checksum
The last two octets are the packet checksum. The first octet of the packet (the 0xFE header) is not included in the checksum.
In addition, a magic character based on the message type is included in the checksum.After the packet (less the header) has been shifted through the CRC accumulator, shift the one-byte magic number through the CRC accumulator to get the final checksum for the packet. I'll put a pointer to some sample code once I get it uploaded (update: here). It can be generated from the MAVLink package, or you can just grab the the MAVLINK_MESSAGE_CRCS from the sample code.
Tridge explains the seed value in a forum comment.
(tl;dr: it catches when people are using incompatible MAVLink XML files.)
Hi Everyone,
I was the one who added the 'seed' in MAVLink 1.0, so maybe I should explain how it works and why it was added.
While we were using MAVLink 0.9 we had a couple of incidents where the XML describing a message that was in active use changed. The change was such that the length of the message didn't change, but the fields did. This meant that when a MAV using the old code was talking to a ground station using updated code that the fields were badly corrupted. The MAVLink 0.9 protocol completely relied on everyone being careful not to change the meaning or format of any existing message. With so many people working on MAVLink this was hard to enforce.
So for MAVLink 1.0 we decided to solve this problem by adding a 1 byte 'seed' to the checksum based on the XML for the message. When the mavlink code generator runs, it takes a checksum of the XML structure for each message and creates an array define MAVLINK_MESSAGE_CRCS. This is used to initialise the mavlink_message_crcs[] array in the C/C++ implementation, and is similarly used in the python implementation.
When the checksum for a message is calculated, this extra byte is added on the end of the data that that the checksum is calculated over. The result is that if the XML changes then the message will be rejected by the recipient as having an incorrect checksum. This ensures that only messages where the sender and recipient are using the same XML structure will get through (or at least it makes a mistake much more unlikely).
If you are doing your own implementation of MAVLink 1.0 you can get this checksum in one of two ways:
you can just use the generated headers, and use MAVLINK_MESSAGE_CRCS to get the right seed for each message type
or you can re-implement the code that calculates the seed.
This is the python code that calculates the seed:
def message_checksum(msg):
'''calculate a 8-bit checksum of the key fields of a message, so we
can detect incompatible XML changes'''
crc = mavutil.x25crc(msg.name + ' ')
for f in msg.ordered_fields:
crc.accumulate(f.type + ' ')
crc.accumulate(f.name + ' ')
if f.array_length:
crc.accumulate(chr(f.array_length))
return (crc.crc&0xFF) ^ (crc.crc>>8)
Notice that it uses the same x25 chcksum that is used at runtime. It calculates a CRC over the message name (such as "RAW_IMU") followed by the type and name of each field, space separated. The order of the fields is the order they are sent over the wire. For arrays, the array length is also added.
My apologies if this seed has caused any confusion. Hopefully the above will explain the reason it was added.
Cheers, Tridge
(toc: MAVLink)