Using C MAVLink Libraries (mavgen)

The MAVLink C library generated by mavgen is a header-only implementation that is highly optimized for resource-constrained systems with limited RAM and flash memory. It is field-proven and deployed in many products where it serves as interoperability interface between components of different manufacturers.

This topic explains how to get and use the library.

Getting Libraries

If you are using a standard dialect then download the MAVLink 2 library from Github: c_library_v2.

The MAVLink 2 library supports both MAVLink 2 and MAVLink 1, and has been built with all standard dialects in the mavlink/mavlink repo. It supersedes the MAVLink 1 library (c_library_v1), and should be used by preference.

If you need libraries for a custom dialect then you will need to install mavgen and generate them yourself. These can then be used in the same way as the pre-generated libraries.

The libraries can be placed/generated anywhere in your project tree. The example below shows them located in: generated/include/mavlink/v2.0/.

The MAVLink 1 pre-built library mavlink/c_library_v1 can be upgraded by simply dropping in the MAVLink 2 library from Github: mavlink/c_library_v2.

The MAVLink 2 C library offers the same range of APIs as was offered by MAVLink1.

The major change from an API perspective is that you don't need to provide a message CRC table any more, or message length table. These have been folded into a single packed table, replacing the old table which was indexed by msgId. That was necessary to cope with the much larger 24 bit namespace of message IDs.

MAVLink 2 usage is then covered in the following sections (this includes Working with MAVLink 1 which explains how you can communicate with both MAVLink 2 and MAVLink 1 (only) libraries.

Adding Libraries

To use MAVLink in your C project, include the mavlink.h header file for your dialect:

#include <your_dialect/mavlink.h>

This will automatically add the header files for all messages in your dialect, and for any dialect files that it includes.

If you support multiple independent dialects you can include these separately (there is no need to separately include dialects that are part of another dialect, but this will do no harm):

#include <common/mavlink.h>
#include <your_dialect/mavlink.h>
#include <another_dialect/mavlink.h>

Do not include the individual message files. If you generate your own headers, you will have to add their output location to your C compiler's search path.

When compiling the project, we recommend that you specify the top-level output directory AND all generated dialects and versions (this will give the greatest compatibility with existing code and examples):

$ gcc ... -I generated/include -I generated/include/common ...

Multiple Streams ("channels")

The C MAVLink library utilizes a "channel" metaphor to allow for simultaneous processing of multiple, independent MAVLink streams in the same program. It is therefore important to use the correct channel for each operation as all receiving and transmitting functions provided by MAVLink require a channel.

If only one MAVLink stream exists, channel 0 should be used by specifying the MAVLINK_COMM_0 constant.

Receiving

MAVLink reception is then done using mavlink_helpers.h:mavlink_parse_char().

Transmitting

Transmitting messages can be done by using the mavlink_msg_*_pack() function, where one is defined for every message. The packed message can then be serialized with mavlink_helpers.h:mavlink_msg_to_send_buffer() and then writing the resultant byte array out over the appropriate serial interface.

It is possible to simplify the above by writing wrappers around the transmitting/receiving code. A multi-byte writing macro can be defined, MAVLINK_SEND_UART_BYTES(), or a single-byte function can be defined, comm_send_ch(), that wrap the low-level driver for transmitting the data. If this is done, MAVLINK_USE_CONVENIENCE_FUNCTIONS must be defined.

Message Signing

Message Signing (authentication) allows a MAVLink 2 system to verify that messages originate from a trusted source.

The C libraries generated by mavgen provide almost everything needed to support message signing in your MAVLink system. The topic C Message Signing explains the remaining code that a system must implement to enable signing using the C library.

This section explains how to use the MAVLink 2 C library to work with MAVLink 1 systems.

Version Handshaking/Negotiation

MAVLink Versions explains the handshaking used to determine the supported MAVLink version of either end of the channel, and how to negotiate the version to use.

The MAVLink 2 library will send packets in MAVLink 2 framing by default. To force sending MAVLink 1 packets on a particular channel you change the flags field of the status object.

For example, the following code causes subsequent packets on the given channel to be sent as MAVLink 1:

mavlink_status_t* chan_state = mavlink_get_channel_status(MAVLINK_COMM_0);
chan_state->flags |= MAVLINK_STATUS_FLAG_OUT_MAVLINK1;

Incoming MAVLink 1 packets will be automatically handled as MAVLink 1. If you need to determine if a particular message was received as MAVLink 1 or MAVLink 2 then you can use the magic field of the message. In c programming, this is done like this:

if (msg->magic == MAVLINK_STX_MAVLINK1) {
   printf("This is a MAVLink 1 message\n");
}

In most cases this should not be necessary as the XML message definition files for MAVLink 1 and MAVLink 2 are the same, so you can treat incoming MAVLink 1 messages the same as MAVLink 2 messages.

MAVLink 1 is restricted to messageIDs less than 256, so any messages with a higher messageID won't be received as MAVLink 1.

It is advisable to switch to MAVLink 2 when the communication partner sends MAVLink 2 (see Version Handshaking). The minimal solution is to watch incoming packets using code similar to this:

if (mavlink_parse_char(MAVLINK_COMM_0, buf[i], &msg, &status)) {

    // check if we received version 2 and request a switch.
    if (!(mavlink_get_channel_status(MAVLINK_COMM_0)->flags & MAVLINK_STATUS_FLAG_IN_MAVLINK1)) {
        // this will only switch to proto version 2
        chan_state->flags &= ~(MAVLINK_STATUS_FLAG_OUT_MAVLINK1);
    }
}

results matching ""

    No results matching ""