Mavlink: Difference between revisions

From Rsewiki
No edit summary
No edit summary
Line 5: Line 5:


This page will give information on how MAVLink is utilized in this project as well as how to update the main flexbot.xml message container and generate the C-headers + Python files needed.
This page will give information on how MAVLink is utilized in this project as well as how to update the main flexbot.xml message container and generate the C-headers + Python files needed.
Questions about this can be referred to JCA or jesper@haahrchristensen.dk


=Prerequisites=
=Prerequisites=
Line 133: Line 131:


Some manual labour goes into hardcoding these functions as they cannot exist dynamically. It is very important that this is completed every single time a message is added. Otherwise the MAVLink interface, GUI and general communication simply cannot work. So please make sure this is complied to at all times!
Some manual labour goes into hardcoding these functions as they cannot exist dynamically. It is very important that this is completed every single time a message is added. Otherwise the MAVLink interface, GUI and general communication simply cannot work. So please make sure this is complied to at all times!
Questions about this can be referred to Jesper Christensen: jesper@haahrchristensen.dk

Revision as of 20:57, 3 December 2017

Introduction

The MAVLink protocol have been implemented in the Flexbot project to secure a standardized communication protocol with as little overhead as possible. This allows for not only transferring data over the serial USB interface between the Teensy and Intel NUC, but also for wireless transformation of all data from the NUC to client(s) and vice versa.

For more information of the MAVLink protocol itself see http://qgroundcontrol.org/mavlink/start.

This page will give information on how MAVLink is utilized in this project as well as how to update the main flexbot.xml message container and generate the C-headers + Python files needed.

Prerequisites

Make sure to have downloaded the newest version of the Flexbot repository and head into code/MAVLink/ and make sure flexbot.xml, Bridge/ and Generator/ is present.

Adding messages to Flexbot

All messages/signals to/from Flexbot are defined in flexbot.xml. A message is defined by an ID, name and description. All signals related to this message is defined by a type (uint8_t, float, etc), name and signal description.

E.g. to add a new message to Flexbot identify the last listed message ID and append to it:

<message id="16" name="TestSignal">
  <description>Test signal for this example</description>
  <field type="float" name="value1">Floating point test value.</field>
  <field type="uint8_t" name="publish">Sets whether or not Teensy should publish this message.</field>
</message>

An important note which goes for all messages is that it must contain the publish signal. This signal allows clients to subscribe to different messages and will save bandwidth as the Teensy only will publish messages that has subscribers.

By updating flexbot.xml nothing magical will happen. In order to integrate the new version of the message definitions C-headers must be generated and the source code on both Teensy and the GUI must be altered to support the new message definitions.

Generating C-headers & Python file

In order to generate the header files used by the Teensy and GUI, a MAVLink generator program is used. This translated the message definition file (flexbot.xml) into a bunch of files related to the chosen language. In order to run the generator, go to /code/MAVLink/Generator and type

python mavgenerate.py

This program should only depend on Python itself and Tkinter. See https://github.com/mavlink/mavlink for references.

In the GUI, choose flexbot.xml and set an output path. Set the protocol to version 1.0 and choose the desired language. By pressing generate, the program should generate a set files if C has been chosen and a single file for Python.

What to do with these is broken down in the sections below.

Python

For Python, the generator produces an error. This is corrected by changing line 13 from

13: from ...generator.mavcrc import x25crc

to

13: from mavcrc import x25crc

Now move the newly generated file to /code/MAVLink/Bridge and replace it with the one already existing.

C

The files generated for C will need to be put into two locations. First copy all the generated files into

/code/Teensy/src/mavlink 

and replace with the ones already existing. Repeat the process for the GUI - files are located at

/code/GUI/flexbot_visualizer/mavlink

Update source code to support new messages

This is considered the most important part. This ensures that the newly introduced messages are supported by software in both the Teensy source code and in the Flexbot Visualizer. There is a bit manual labour here, but with the given MAVLink protocol there is no way around it.

Updating Teensy source code

A few steps needs to be taken here to ensure that the new message is supported. First locate and open

/code/Teensy/src/command.cpp

Starting from line 320 or so is a function called

void MAVLink_msg_handler(mavlink_message_t _msg)

This is where the incomming MAVLink messages will be processed. In order to support new messages there needs to be a section that processes each message. Follow the syntax in the code to append to the function.

E.g. for a message with ID = 3 the processing will look similar to this

else if(ID == 3)
{
  // DCCmd
  mavlink_dcwheelcmd_t msg;
  mavlink_msg_dcwheelcmd_decode(&_msg,&msg);
  dc_wheel.set(msg.dutycycle,msg.direction);
  dc_wheel.publish = msg.publish;
}

I.e. a struct available from the MAVLink generated files needs to be initialised. This struct needs to be the one that matches the message. Next the message is decoded and put into the struct. From the struct all signals will be available as showed in the example and existing source code.

The general idea is that each message is associated with a class (or signal) that has an attribute called publish. This will become useful when printing data over the USB serial interface. This is seen by looking at

void printSensorStatus()

in command.cpp. This function call all classes' print_data()-function which could look similar to this

void Linear_Actuator::print_data()
{
  if (publish)
  {
    uint8_t buf[2041];
    mavlink_message_t msg;
    mavlink_msg_act1sts_pack(0,0,&msg,0,current, publish);
    uint16_t len = mavlink_msg_to_send_buffer(buf,&msg);
    usb_serial_write(buf,len);
  }
}

where the data is printed only if publish is set.


This is basically what needs to be done in the Teensy source code. It is important to make sure that each received signal is decoded and processed.

Updating Flexbot Visualizer source code

Two files needs to updated here. First locate and open

/code/GUI/flexbot_visualizer/receiver.cpp

and go to the function

QList<int> Receiver::process_MAVLink_msg(mavlink_message_t _msg)

As with the Teensy source code, the GUI also needs to process all incoming MAVLink messages. An example to this could be

else if(ID == 3)
{
  // DCCmd
  mavlink_dcwheelcmd_t msg;
  mavlink_msg_dcwheelcmd_decode(&_msg,&msg);
  flexbot->update(flexbot->MavIDtoID(ID),msg.speed);
  IDarray.push_back(flexbot->MavIDtoID(ID));
  flexbot->update(flexbot->MavIDtoID(ID)+1,msg.publish);
  IDarray.push_back(flexbot->MavIDtoID(ID)+1);
}

Again the message is decoded, and the signal values are used to update the local values held by the GUI. Follow the examples already existing in the source code.

Next locate and open

/code/GUI/flexbot_visualizer/sender.cpp

and go to the function

void Sender::process_mavlink_message(int ID)

Here each value for a given signal is retrieved from the GUI and packed as a MAVLink struct. An example of this is

else if(ID == 3)
{
 // DCCmd
 double speed = flexbot->getValue("DCWheelCmd","speed");
 int dc = flexbot->getValue("DCWheelCmd","dutycycle");
 int dir = flexbot->getValue("DCWheelCmd","direction");
 int publish = flexbot->getValue("DCWheelCmd","publish");
 mavlink_msg_dcwheelcmd_pack(0,0,&msg,speed,dc,dir,publish);
}

Follow the examples already existing in the source code.

Closing remarks

This is all that needs to be done to add new signals/messages to Flexbot.

Some manual labour goes into hardcoding these functions as they cannot exist dynamically. It is very important that this is completed every single time a message is added. Otherwise the MAVLink interface, GUI and general communication simply cannot work. So please make sure this is complied to at all times!

Questions about this can be referred to Jesper Christensen: jesper@haahrchristensen.dk