Mavlink: Difference between revisions

From Rsewiki
 
(24 intermediate revisions by the same user not shown)
Line 10: Line 10:
=Prerequisites=
=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.
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.
It is further needed to install "python future" to run the MAVgenerate python application.
$ pip install future


=Adding messages to Flexbot=
=Adding messages to Flexbot=
All messages/signals to/from Flexbot are defined in flexbot.xml.  
 
MAV is used between the main processor (the base_node_ros node) and the 5 Teensy controllers.
 
== file structure ==
 
code
  +-- base_node_ros          // ros node (accessed from catkin workspace)
  |    +-- include          // directory for generated MAV library
  |          +-- flexbot_2  // generated directory
  +-- MAVLink                // MAV link definition directory
  |    +-- flexbot_2.xml    // definition of MAV link
  |    +-- Generator        // MAV library generator (python code)
  |          +-- mavgenerate.py  // python code for MAV library generation
  +-- teensy_2                // code for teensy
  |    +-- src              // source code
  |    +-- Makefile          // normal makefile (not using arduino IDE)
  |    +-- teensy_2.hex      // generated code for teensy
  |    +-- teensy3          // link to teensyduino installation: arduino-1.x.y/hardware/teensy/avr/cores/teensy3
  |    +-- libteensy        // link to teensyduin0 installation: arduino-1.x.y/hardware/teensy/avr/libraries
  |    +-- tools            // link to teensyduino installation: arduino-1.x.y/hardware/tools
  +-- 99-flexbot-legs.rules  // definition of leg interface - should be linked from /udev/rules.d/
 
== UDEV device names ==
 
The 99-flexbot-legs.rules holds rules that makes a teensy device unique, i.e. makes a symbolic link that is unique
regardless of connection order.
 
make a link in /etc/udev/rules.d/ to this file, e.g.
 
cd /etc/udev/rules.d
sudo ln -s /home/local/flexbot/code/99-fklexbot-legs.rules
to find the serial number for a device, connect just one device and
 
udevadm info -q all -n /dev/ttyACM0
 
find the ID_SERIAL_SHORT=xxxxx
and insert that number into ATTRS{serial}=="xxxxx"
to make udev read the changes you probably need:
 
sudo udevadm control --reload-rules
 
The rules in 99-fklexbot-legs.rules for the 5 Teensy processors look something like:
 
SUBSYSTEM=="tty", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0483", ATTRS{serial}=="4004150", SYMLINK+="flexbot_base"
SUBSYSTEM=="tty", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0483", ATTRS{serial}=="4145230", SYMLINK+="flexbot_leg1"
SUBSYSTEM=="tty", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0483", ATTRS{serial}=="4000001", SYMLINK+="flexbot_leg2"
SUBSYSTEM=="tty", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0483", ATTRS{serial}=="4000002", SYMLINK+="flexbot_leg3"
SUBSYSTEM=="tty", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0483", ATTRS{serial}=="4000003", SYMLINK+="flexbot_leg4"
 
== Message definition ==
 
All messages/signals to/from Flexbot are defined in flexbot_2.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.  
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:
E.g. to add a new message to Flexbot:


  <message id="16" name="TestSignal">
  <message id="16" name="TestSignal">
Line 25: Line 80:
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.
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.  
By updating flexbot_2.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=
== 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 translates 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
In order to generate the header files used by the Teensy and GUI, a MAVLink generator program is used. This translates the message definition file (flexbot_2.xml) into a bunch of files related to the chosen language. In order to run the generator, go to /code/MAVLink/Generator and type


cd code/MAVLink/Generator
  python mavgenerate.py
  python mavgenerate.py


This program should only depend on Python itself and Tkinter. See https://github.com/mavlink/mavlink for references.
This program should only depend on Python itself future 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 of files if C has been chosen and a single file for Python.
In the GUI, '''choose XML file'''


What to do with these is broken down in the sections below.
~/flexbot/code/MAVLink/flexbot_2.xml


==Python==
and set '''output path''' to
For Python, the generator produces an error. This is corrected by changing line 13 from
 
  13: from ...generator.mavcrc import x25crc
  ~/flexbot/code/base_node_ros/include
to
 
13: from mavcrc import x25crc
Set the protocol to version 1.0 and choose the desired '''language (C)'''.  
Now move the newly generated file to /code/MAVLink/Bridge and replace it with the one already existing.  


==C==
By pressing generate, the program should generate a set of files if C has been chosen and a single file for Python.


The generated MAV files should be generated to
The generated MAV C files is generated into


~/flexbot/code/base_node_ros/include
~/flexbot/code/base_node_ros/include


Here it will make a subdirectory called flexbot_2 with the main file to include mavlink.h
Here it will make a subdirectory called flexbot_2 with the main file to include "mavlink.h"


====Old code====
=Old code=


The old code generated by Jesper and Servet need this:
The old code generated by Jesper and Servet need this:
Line 63: Line 118:
  /code/GUI/flexbot_visualizer/mavlink
  /code/GUI/flexbot_visualizer/mavlink


=Update source code to support new messages=
===Python===
 
The Python code is used by the Jesper/Servet code only:
 
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.
 
=Update Teensy and bridge and visualizer source code to support new messages=
 
'''NB!''' most of this is old code, this is replaced with a ROS interface (base_node_ros).
 
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.
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==
==Updating Teensy source code==
A few steps needs to be taken here to ensure that the new message is supported. First locate and open
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
  /code/Teensy/src/command.cpp
Starting from line 320 or so is a function called  
 
Starting from (about) line 320 is a function called  
 
  void MAVLink_msg_handler(mavlink_message_t _msg)
  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.  
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.  


Line 146: Line 219:


Questions about this can be referred to Jesper Christensen: jesper@haahrchristensen.dk
Questions about this can be referred to Jesper Christensen: jesper@haahrchristensen.dk
----
--[[User:Jca|Jca]] ([[User talk:Jca|talk]]) 13:02, 9 June 2018 (CEST)

Latest revision as of 17:09, 9 November 2018

Back to Flexbot main page

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 transfer 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.

It is further needed to install "python future" to run the MAVgenerate python application.

$ pip install future

Adding messages to Flexbot

MAV is used between the main processor (the base_node_ros node) and the 5 Teensy controllers.

file structure

code
  +-- base_node_ros           // ros node (accessed from catkin workspace)
  |     +-- include           // directory for generated MAV library
  |           +-- flexbot_2   // generated directory
  +-- MAVLink                 // MAV link definition directory
  |     +-- flexbot_2.xml     // definition of MAV link 
  |     +-- Generator         // MAV library generator (python code)
  |           +-- mavgenerate.py  // python code for MAV library generation
  +-- teensy_2                // code for teensy
  |     +-- src               // source code
  |     +-- Makefile          // normal makefile (not using arduino IDE)
  |     +-- teensy_2.hex      // generated code for teensy
  |     +-- teensy3           // link to teensyduino installation: arduino-1.x.y/hardware/teensy/avr/cores/teensy3
  |     +-- libteensy         // link to teensyduin0 installation: arduino-1.x.y/hardware/teensy/avr/libraries
  |     +-- tools             // link to teensyduino installation: arduino-1.x.y/hardware/tools
  +-- 99-flexbot-legs.rules   // definition of leg interface - should be linked from /udev/rules.d/

UDEV device names

The 99-flexbot-legs.rules holds rules that makes a teensy device unique, i.e. makes a symbolic link that is unique regardless of connection order.

make a link in /etc/udev/rules.d/ to this file, e.g.

cd /etc/udev/rules.d
sudo ln -s /home/local/flexbot/code/99-fklexbot-legs.rules

to find the serial number for a device, connect just one device and

udevadm info -q all -n /dev/ttyACM0

find the ID_SERIAL_SHORT=xxxxx and insert that number into ATTRS{serial}=="xxxxx" to make udev read the changes you probably need:

sudo udevadm control --reload-rules

The rules in 99-fklexbot-legs.rules for the 5 Teensy processors look something like:

SUBSYSTEM=="tty", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0483", ATTRS{serial}=="4004150", SYMLINK+="flexbot_base"
SUBSYSTEM=="tty", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0483", ATTRS{serial}=="4145230", SYMLINK+="flexbot_leg1"
SUBSYSTEM=="tty", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0483", ATTRS{serial}=="4000001", SYMLINK+="flexbot_leg2"
SUBSYSTEM=="tty", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0483", ATTRS{serial}=="4000002", SYMLINK+="flexbot_leg3"
SUBSYSTEM=="tty", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0483", ATTRS{serial}=="4000003", SYMLINK+="flexbot_leg4"

Message definition

All messages/signals to/from Flexbot are defined in flexbot_2.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:

<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_2.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 translates the message definition file (flexbot_2.xml) into a bunch of files related to the chosen language. In order to run the generator, go to /code/MAVLink/Generator and type

cd code/MAVLink/Generator
python mavgenerate.py

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

In the GUI, choose XML file

~/flexbot/code/MAVLink/flexbot_2.xml 

and set output path to

~/flexbot/code/base_node_ros/include

Set the protocol to version 1.0 and choose the desired language (C).

By pressing generate, the program should generate a set of files if C has been chosen and a single file for Python.

The generated MAV C files is generated into

~/flexbot/code/base_node_ros/include

Here it will make a subdirectory called flexbot_2 with the main file to include "mavlink.h"

Old code

The old code generated by Jesper and Servet need this:

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

Python

The Python code is used by the Jesper/Servet code only:

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.

Update Teensy and bridge and visualizer source code to support new messages

NB! most of this is old code, this is replaced with a ROS interface (base_node_ros).

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 (about) line 320 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



--Jca (talk) 13:02, 9 June 2018 (CEST)