How to use¶
Platform support¶
Framework:
Arduino
This library is made to be used with:
ESP32 family
Teensy 4.X family
Generate headers for custom messages¶
The mavlink headers are generated using the mavlink generator. A shell script is provided for easy generation. The common messages set is already generated and can be found in the libDM_mavlink/autogen_mavlink/common folder.
If you need to add messages to the set, you can modify libDM_mavlink/message_definition/sysrox.xml and add your messages. Then, you can generate the headers using the following command:
./generate_mavlink.sh
More informations about the mavlink generator can be found here: https://mavlink.io/en/
Necessary inclusions¶
The header of all selected messages selected messages has to be included. The header of libDM_mavlink also
#include "libDM_mavlink.hpp"
#include "autogen_mavlink/common/mavlink_msg_attitude.h"
#include "autogen_mavlink/sysrox/sysrox.h"
Message reception¶
1. Create a MAVLINK_UTILS object¶
Important
API ref: MAVLINK_UTILS
Example
MAVLINK_UTILS mavlink(&streamObj);
2. (optional) Add a MAVLINK_STREAM object¶
If no interface has already been specified, you can configure an interface and add it to the MAVLINK_UTILS
object
Important
API ref: MAVLINK_UTILS::addMavlinkStream()
Example
// Initialize serial link
Serial2.setRxBufferSize(200);
Serial2.setTxBufferSize(200);
Serial2.begin(921600, SERIAL_8N1, pinProtocolRx, pinProtocolTx);
mavlink.addMavlinkStream(&Serial2);
3. Add messages to monitor¶
Important
API ref: MAVLINK_UTILS::addMsgToMonitor()
Example
mavlink.addMsgToMonitor(MAVLINK_MSG_ID_ATTITUDE);
mavlink.addMsgToMonitor(MAVLINK_MSG_ID_SYSROX_INS_GENERIC_CALIBRATION_BARO_SENSOR_CORRECTION);
4. Get your own subset of messages list¶
Important
API ref: MAVLINK_UTILS::getMonitoredMsgsList()
, MAVLINK_MSG_LIST::getSubset()
Example
// Get own subset of message to receive (all messages in this case)
std::vector<uint32_t> messageToReceiveIdx = {
MAVLINK_MSG_ID_ATTITUDE,
MAVLINK_MSG_ID_SYSROX_INS_GENERIC_CALIBRATION_BARO_SENSOR_CORRECTION};
MAVLINK_MSG_LIST myReceiveList = mavlink.getMonitoredMsgsList()->getSubset(messageToReceiveIdx);
5. (optional) Save references for the monitored messages¶
To avoid getting the reference from the list every time, a reference can be saved at init for performance
Important
API ref: MAVLINK_MSG_LIST::getMsg()
Example
// Get references to the serialized messages. Not mandatory as we can use the list but more efficient:
MAVLINK_MSG* attitudeMsgRef = myReceiveList.getMsg(MAVLINK_MSG_ID_ATTITUDE);
MAVLINK_MSG* calibrationMsgRef = myReceiveList.getMsg(MAVLINK_MSG_ID_SYSROX_INS_GENERIC_CALIBRATION_BARO_SENSOR_CORRECTION);
6. Initialize the deserialized structs to fill with received messages¶
Example
mavlink_attitude_t attitudeReceived;
mavlink_sysrox_ins_generic_calibration_baro_sensor_correction_t calibrationReceived;
7. Call updateMonitoredMessages(buffer, bufferLength) at every step¶
The updateMonitoredMessages has to be called periodically and feeded with the received buffer on some hardware interface. It will update the monitored messages list with the new messages received.
Important
Example
uint8_t receptionSerialBuffer[MAVLINK_MAX_PACKET_LEN];
size_t size = Serial2.available();
OP::UART::readBytesBuffer(&Serial2, receptionSerialBuffer, size);
mavlink.updateMonitoredMessages(receptionSerialBuffer, size);
8. Get the last message of a specific ID (or all)¶
The messages have been updated automatically with updateMonitoredMessages calls. It is the possible to check if the message is new and get the last message of a specific ID.
8.1 Check if message has been received on some registered interface¶
To check if the message has been updated, you can use the built in method inside your MAVLINK_MSG_LIST
object: MAVLINK_MSG_LIST::getIsNew()
If a reference to the MAVLINK_MSG
has been saved during initialization, it is also possible to check the
‘mIsNew’ attribute of the message.
With the reference created during initialization
Example
attitudeMsgRef->mIsNew
With the list object
Example
myReceiveList.getIsNew(MAVLINK_MSG_ID_ATTITUDE)
8.2 Method 1: Get the last updated message¶
Example
if (myReceiveList.getIsNew(MAVLINK_MSG_ID_ATTITUDE)) // or attitudeMsgRef->mIsNew
{
Serial.println("Attitude received");
// Decode the message. You can get the serialized message with direct alias (created
// during initialization like in this example) or MAVLINK_MSG* attitudeMsgRef =
// myReceiveList.getMsg(MAVLINK_MSG_ID_ATTITUDE)
mavlink_msg_attitude_decode(&attitudeMsgRef->getMavlinkMsg(), &attitudeReceived);
Serial.println(attitudeReceived.yaw);
Serial.println(attitudeReceived.pitch);
Serial.println(attitudeReceived.roll);
Serial.println(attitudeReceived.time_boot_ms);
}
if (myReceiveList.getIsNew(
MAVLINK_MSG_ID_SYSROX_INS_GENERIC_CALIBRATION_BARO_SENSOR_CORRECTION))
{
Serial.println("Calibration received");
mavlink_msg_sysrox_ins_generic_calibration_baro_sensor_correction_decode(
&calibrationMsgRef->getMavlinkMsg(), &calibrationReceived);
for (size_t i = 0; i < 3; i++)
{
Serial.print(calibrationReceived.xyzBias[i]);
Serial.print(" ");
}
Serial.println();
Serial.println(calibrationReceived.opcDeltaPressure);
for (size_t i = 0; i < 5; i++)
{
Serial.print(calibrationReceived.gTemperatureDriftValue[i]);
Serial.print(" ");
}
Serial.println();
}
8.3. Method 2: Get only some field of the last received message
Example
if (myReceiveList.getIsNew(MAVLINK_MSG_ID_ATTITUDE)) // or attitudeMsgRef->mIsNew
{
Serial.println("Attitude received");
Serial.println(mavlink_msg_attitude_get_yaw(&attitudeMsgRef->getMavlinkMsg()));
}
Message emission¶
The parts marked as optional are included if you choose periodic sending of messages. This kind of use is not recommended as it is less efficient than sending messages when they are ready.
1. Create a MAVLINK_UTILS object¶
Important
API ref: MAVLINK_UTILS
Example
MAVLINK_UTILS mavlink(&streamObj);
2. Add a MAVLINK_STREAM object¶
If no interface has already been specified, you can configure an interface and add it to the
MAVLINK_UTILS
object
Important
API ref: MAVLINK_UTILS::addMavlinkStream()
Example
// Initialize serial link
Serial2.setRxBufferSize(200);
Serial2.setTxBufferSize(200);
Serial2.begin(921600, SERIAL_8N1, pinProtocolRx, pinProtocolTx);
mavlink.addMavlinkStream(&Serial2);
3. (optional) Add messages to sending list¶
The messages are added to a sending list with a source list for each message.
Important
API ref: MAVLINK_UTILS::addMsgToSendingList()
, MAVLINK_SOURCE
Example
// We want to send these messages on the serial interface
std::vector<MAVLINK_SOURCE> sendingInterfaces = {MAVLINK_SOURCE::SOURCE_SERIAL};
mavlink.addMsgToSendingList(MAVLINK_MSG_ID_ATTITUDE, sendingInterfaces);
mavlink.addMsgToSendingList(
MAVLINK_MSG_ID_SYSROX_INS_GENERIC_CALIBRATION_BARO_SENSOR_CORRECTION,
sendingInterfaces);
4. (optional) Get your own subset of messages list¶
Important
API ref: MAVLINK_UTILS::getMonitoredMsgsList()
, MAVLINK_MSG_LIST::getSubset()
Example
// Get own subset of message to send (all messages in this case)
std::vector<uint32_t> messageToSendIdx = {
MAVLINK_MSG_ID_ATTITUDE,
MAVLINK_MSG_ID_SYSROX_INS_GENERIC_CALIBRATION_BARO_SENSOR_CORRECTION};
MAVLINK_MSG_LIST mySendList =
mavlink.getMsgsToSendList()->getSubset(messageToSendIdx); // optional
5. (optional) Save references for the monitored messages¶
To avoid getting the reference from the list every time, a reference can be saved at init for performance
Important
API ref: MAVLINK_MSG_LIST::getMsg()
Example
// Get references to the serialized messages:
MAVLINK_MSG* attitudeMsgRef = mySendList.getMsg(MAVLINK_MSG_ID_ATTITUDE);
MAVLINK_MSG* calibrationMsgRef = mySendList.getMsg(MAVLINK_MSG_ID_SYSROX_INS_GENERIC_CALIBRATION_BARO_SENSOR_CORRECTION);
6. Initialize generic message and the deserialized structs¶
Example
// Initialize generic message
mavlink_message_t genericMsg = mavlink_message_t();
// Get the deserialized structs for the messages that need to be sent
mavlink_attitude_t attitudeToSend;
mavlink_sysrox_ins_generic_calibration_baro_sensor_correction_t calibrationToSend;
7. Update messages and send them¶
Update the messages you want to send and indicate they are ready to be sent. Once done, the message has to be serialized
into the generic message using mavlink autogenerated function. The message can then be sent manually using
MAVLINK_UTILS::sendMessage()
or automatically using MAVLINK_MSG::updateMsgForSend()
and with calling
periodically MAVLINK_UTILS::sendMessages()
.
Tip
As the MAVLINK_UTILS::sendMessages()
is called every loop step, the direct call to MAVLINK_UTILS::sendMessage()
when the message is filled is recommended. In this case, no need to use the sending list. In this case the steps are
just to fill your mavlink messages, serialize it and use MAVLINK_UTILS::sendMessage()
to send it.
Important
API ref: MAVLINK_MSG::updateMsgForSend()
, MAVLINK_UTILS::sendMessage()
,
MAVLINK_UTILS::sendMessages()
The following examples shows how to send the 2 messages manually and automatically at 200Hz.
Manually
Example
long t_now = millis();
while (true)
{
// Send every 5 ms
if ((millis() - t_now) > 5)
{
t_now = millis()
// Update and send the attitude message
attitudeToSend.time_boot_ms += 2;
attitudeToSend.pitch = 0.666;
attitudeToSend.roll = 0.777;
attitudeToSend.yaw = 0.888;
mavlink_msg_attitude_encode(0, 0, &genericMsg, &attitudeToSend);
mavlink.sendMessage(MAVLINK_SOURCE::SOURCE_SERIAL, genericMsg);
// Update and send the calibration message
calibrationToSend.xyzBias[0] = 0.111;
calibrationToSend.xyzBias[1] = 0.222;
calibrationToSend.xyzBias[2] = 0.333;
calibrationToSend.opcDeltaPressure = 0.444;
calibrationToSend.gTemperatureDriftValue[3] = 0.555;
mavlink_msg_sysrox_ins_generic_calibration_baro_sensor_correction_encode(
0, 0, &genericMsg, &calibrationToSend);
mavlink.sendMessage(MAVLINK_SOURCE::SOURCE_SERIAL, genericMsg); // custom immediate sending
}
}
Automatically
Example
long t_now = millis();
while (true) // main loop
{
// Send every 5 ms
if ((millis() - t_now) > 5)
{
t_now = millis()
// Update and send the attitude message
attitudeToSend.time_boot_ms += 2;
attitudeToSend.pitch = 0.666;
attitudeToSend.roll = 0.777;
attitudeToSend.yaw = 0.888;
mavlink_msg_attitude_encode(0, 0, &genericMsg, &attitudeToSend);
attitudeMsgRef->updateMsgForSend(genericMsg);
// Update and send the calibration message
calibrationToSend.xyzBias[0] = 0.111;
calibrationToSend.xyzBias[1] = 0.222;
calibrationToSend.xyzBias[2] = 0.333;
calibrationToSend.opcDeltaPressure = 0.444;
calibrationToSend.gTemperatureDriftValue[3] = 0.555;
mavlink_msg_sysrox_ins_generic_calibration_baro_sensor_correction_encode(
0, 0, &genericMsg, &calibrationToSend);
calibrationMsgRef->updateMsgForSend(genericMsg);
}
mavlink.sendMessages(); // send messages when they are ready
}