New message and variables in APM Planner 2

Correct, all the headers and it should work as expected. MAVProxy would be the same, though the easiest for MAVProxy or any component using submodules it to point the submodule at a fork of mavlink with your changes in the branch you want.

I am very much stuck…

Today I generated the headers for the messages on the pixhawk in a separate directory (using v1.0) and copied them into the relevant places in apm_planner/libs/mavlink/include/mavlink/v1.0/. I recompiled and nothing was different.

I also tried simply adding the single file mavlink_msg_external_data.h (the file I am testing for sending more data) into the …/v1.0/ardupilotmega directory and adding it to the includes in ardupilotmega.h. It compiled, but didn’t show the data in the GUI.

I played around with editing some other message headers, like the mavlink_msg_battery2.h, and did see minor changes in the GUI, but nothing that I could exploit.

Do you have any ideas on how I should procede?

I also tried just adding more variables to the message definition for battery2, already in ardupilot’s ardupilotmega.h, and then recompiling for ardupilot. Then I generated the mavlink v1.0 file for battery2 and putting it in the ardupilotmega folder for apm_planner. After recompiling, the battery2 message no longer appeared.

I can successfully send information using the battery2 message, but only 2 variables, since that is the original definition of it.

There are global headers that are also modified so it’s not as easy as adding the header for the new message. You need to whole output from the generator between amp planner 2.0 and autopilot to be the same

Could you give some advice on how exactly I should do this? I have generated the mavlink messages for ardupilot (but using v1.0, and language C) and routed the output from the generator into the directory apm_planner/libs/mavlink/include/mavlink/v1.0/ (tried this both with and without deleting all files and directories here first as well). The code requires a few minor edits after this, but compiles fairly easily. But then once I run APM Planner, there is only a placeholder for a message called EMPTY, which only contains a char[0].

I had to regenerate the messages for v1.0 because make px4-v2-upload only makes v2.0 messages.

Just tried doing a similar thing with just the common/ library: generated the mavlink headers for the ardupilot’s common.xml (with an added definition for an EXTERNAL_DATA message with ID=227, which I believe does not conflict with any other messages in the library) and copied them into the (emptied) common/ directory for apm_planner. Also had to copy the MAV_AUTOPILOT_TYPE enum from the original common.h into the new common.h, as it did not include a definition for MAV_AUTOPILOT_PIXHAWK. Also had to remove passing of *_MIN_LEN variables from all newly generated headers.

The code compiles after I do this, and the program runs without errors, but I still have no luck displaying my new message…

Any ideas? Anybody?

Edit: code is here, new mavlink message is here

Hi,

I’ve done some work on something similar (extending mavlink to make use of message id 227 to send, and graph some extra data in real-time). Are you constrained to using APM planner? I did this in Mission Planner and can share how I did it there if you like?

I update APM Planner 2.0 to the latest MAVLink the other day. There was some minor changes in the mavgen output. You’ll find the code a drop in replacement now.

Hello,

@uzapm, I am working exactly on the same thing these days. Have you sorted out how to generate v1.0 messages? If I build apm planner with v2.0 MAVLink messsage headers, it fails. I created a post in this forum https://discuss.ardupilot.org/t/custom-data-sending-via-mavlink-protocol-dev/21343/2 and I put steps which I have done in the vehicle code, maybe you are missing something there, check it out.

I am stuck at building APM Planner with new headers, maybe we will solve this problem finally.

Good luck

Oops, I actually solved this issue months ago and forgot to update this page.

This will assume that you added your new mavlink message to the common.xml file.

The best way that I’ve found to accomplish adding a new mavlink message to your system, for use with APM Planner 2.0, is to

  • Fork the mavlink repository (https://github.com/ardupilot/mavlink). Clone it to your system, make your to the message definitions. Most likely you should make these changes in the common.xml file, although other people may have different opinions on that.
  • Fork the ardupilot repository (https://github.com/ardupilot/ardupilot) and replace the existing mavlink submodule with the one you have just edited. This way the ArduPilot compilation/build will always be smooth. Then compile, upload to your pixhawk and be sure your ArduPilot system itself is working.
  • I would then recommend testing your message by using mavproxy, because it is much easier and faster to work with than APM Planner 2.0. Install mavproxy using apt-get if you’re using linux.
  • Generate your mavlink files by going to the mavlink repository that you have cloned and running mavgenerate.py. Use the GUI that pops up to select common.xml as the input file and then select common.py as the output file name. Use python as the language. This is where you can select whether you want to use mavlink v1 or v2. For this mavproxy test you’ll want to use v2. Once common.py is generated, find the auto-generated function for your message and add some obnoxious print statement that will let you know that your message is working. Copy and replace the common.py file that came with your mavproxy installation. I don’t have the path to this file with me right now but if you need it I can find it. Once you replace this file with your own, you can run something like mavproxy.py --master=/dev/ttyUSB0,115200 --mav20 --dialect common which will start mavproxy communicating with your pixhawk using the common dialect. If everything goes well, you should be able to see your obnoxious print statement every time your custom message comes in. The reason I prefer to test with mavproxy is that it takes almost no time to compile, whereas APM Planner 2.0 takes a long time to compile and is much more finicky.
  • If you can confirm that your message is working using mavproxy, then you can start trying to get it to work with APM Planner. Clone the APM Planner 2.0 repository (https://github.com/ArduPilot/apm_planner). In the mavlink repo, use mavgenerate.py to generate mavlink files for all files in the mavlink/message_definitions/v1.0/ directory using the the protocol v1.0, and language C. I would recommend putting all of your output files from this process into a single directory. Then copy them all into apm_planner/libs/mavlink/include/mavlink/v1.0 directory, removing all of the original files first (I would suggest backing up the original files for ease.). Then recompile APM Planner as per the directions on the github page and if nothing terrible happened, your message will show up in APM Planner as all of the standard messages do.
2 Likes

Thank you!

I will try steps you have recommended, but I followed the tutorial at ardupilot dev web and I edited mavlink submodule already in ardupilot repo, build is ok, everything seem to be working, headers were generated in the message_definitions directory. I missed the part with mavgenerate.py, so I hope it will help. I will let you know!

EDIT::

  1. Is this path the right one? (for common.py file): /usr/local/lib/python2.7/dist-packages/pymavlink/dialects/v20/

  2. If I understood what you were suggesting, this is the screen where my message should appear? When I send message by gcs().send_message(MY_MSG_DEF)?

  3. I am able to see where the problem is - when I run “status” command in MAVProxy console, besides standard params it prints out this: BAD_DATA {unknown MAVLink message ID 145, data:…. My message ID is 145 so I suppose that the message is being sent via MAVLink, but problem is still in the headers …

  1. That does appear to be the correct path. Careful when editing the common.py, as if you write an erroneous command in the file, it may regenerate the file without warning.

  2. It seems mavproxy.py is working correctly, however I see nothing on that particular screen that is indicative of your added message. If you edit the common.py file, you can use print statements to cause your message to print messages to that screen. Each message in common.py has its own class definition, with two functions init and pack, and you can print any messages or variables from the init function. If you need to, consider adding a command similar to the following before your gcs().send_message(MY_MSG_DEF) command:
    gcs().send_text(MAV_SEVERITY_INFO, “Hello, mavproxy!”);
    This will cause the ArduPilot firmware itself to send a message to the mavproxy console even if your custom message itself is not working.

  3. One potential problem I see, right of the bat, is that according to the definition of the mavlink common dialect, and in common.xml, there is already a message with ID=145. Unless you deleted the definition for the original message, which may cause problems, this is one likely problem. I would suggest using IDs between 235 and 240. I personally use 237 and 238.

Hello again,

I changed Message ID to 237, still getting same BAD_DATA response.

It looks like this:


The message ID is good and even some of the data looks good (I am sending 6 numbers, 1,2,3,4,5,6).

I think I am going to implement it in the APM planner already, since that is what I need and I think that message is being sent (due to the screenshot) so the problem, I think, somewhere in the dependencies - header files.

The gcs().send_text(MAV_SEVERITY_INFO, "Hello, mavproxy!") command was working long time ago, I tried it.

Thank you so much for your help!

Let me know how it goes!

Hello again,

I needed to take o week off, because I was ill.

As I am reading your “recommended steps” again, I may see a little misunderstanding in our conversation, which I was not able to see before.

I am not editing common.py file, I think I do not even need it. I am little bit further than that. I am developing 3 months already and this is the last part of the development. I am fairly familiar with ardupilot vehicle code. I would like to point out, that I want to send my message from vehicle code, not in common.py - or is that needed? (Editing of common.py if I am already sending that message from ardupilot code).

Hello,

So it is finally working!

Thank you @uzapm for your time.

For the others, I can write simple steps, what I have done (to work with MAVProxy):

  • Edit /ardupilot/modules/mavlink/message_definitions/v1.0/common.xml by adding your message
  • Build whole project
  • There should be updated common.py file in ardupilot/modules/mavlink/ , check if your message is there (search in common.py for the definitions)
  • If the file is not updated or does not contain definitions needed for your message, generate common.py file with mavgenerate.py also located in ardupilot/modules/mavlink/, it will open GUI, I guess you will know how to work with it (command to launcha mavgenerate python mavgenerate.py
  • Copy /ardupilot/modules/mavlink/message_definitions/v1.0/common.xml to /usr/local/lib/python2.7/dist-packages/pymavlink/message_definitions/v1.0/
  • Copy /home/edo/ardupilot/modules/mavlink/common.py to /usr/local/lib/python2.7/dist-packages/pymavlink/dialects/v10/

Launch mavproxy by: mavproxy.py --master=/dev/ttyACM3,115200 --mav10 --dialect common
You may have noticed versions used here, I used v1.0, you can use whatever you want, but keep in mind you have to look out for it when copying, launching mavproxy etc.

This is not all work you have to do. Sending the message right way is anothern concern, maybe I will write full tutorial for this when finish my work.

EDIT: @uzapm this is the funny one! My message contained parameter with name ‘is’ , so the mavgenerate.py generated a function, it looked like this def __init__(self, time_boot_ms, esc_id, speed, vs, is, vbus, pwm, temp). When I tried to run mavproxy it gaave me error at ‘is’, because python thought it is a comparator :smiley:

1 Like

Glad you got it working! That is funny about the is haha.

As a clarification, using mavproxy is just a quicker way of testing that the message itself is being sent correctly. I did this because when I edited the APM Planner code, I had a bit of trouble getting it to display the message, although the rest of APM Planner was working. So I didn’t know if my edits to APM Planner were not working, or if the message in the Ardupilot code itself was not working. It is much easier to test this with mavproxy than APM Planner.

I would like to point out, that I want to send my message from vehicle code, not in common.py - or is that needed? (Editing of common.py if I am already sending that message from ardupilot code).

The messages are all sent from the vehicle code. Mavproxy is just a simpler way than APM Planner to test that the vehicle code is sending the message correctly. So editing common.py will not send the message, but rather just receive it from the vehicle and allow you to check that it is sending correctly. (I understand that you know this already, I’m just adding this information to clarify for anyone else who happens to be doing this same thing.)

I know that is not the best way to answer few months after but this topic was really helpful for me and I would like to add few details for people who would like to make it works with Mission Planner and SITL rather than a real drone. Hope it could help some people (I adapt the description of @eMrazSVK to give the full steps).

ArduPilot side:

  • Edit /ardupilot/modules/mavlink/message_definitions/v1.0/common.xml by adding your message
  • Build whole project
  • Create your appropriate function in ArduPilot as explain in the other topic
  • Different from this topic. Generate ardupilotmega.py file with mavgenerate.py also located in ardupilot/modules/mavlink/, it will open GUI, the input is message_definitions/ardupilotmega.xml and for the output create a new file called ardupilotmega.py (command to launch mavgenerate python mavgenerate.py)
  • Copy ardupilot/modules/mavlink/ardupilotmega.py to /usr/local/lib/python2.7/dist-packages/pymavlink/dialects/v10/.
  • Run sim_vehicle.py. Ardupilot use by default this dialect (ardupilotmega v10) if no special parameters has been added so if you replaced the file it should find your message. If you followed the instructions of last messages it can also works by adding --mavproxy-args "--dialect common" parameters when you run sim_vehicle.py. If you still have error with BAD_DATA, you may try to copy /ardupilot/modules/mavlink/message_definitions/v1.0/common.xml to /usr/local/lib/python2.7/dist-packages/pymavlink/message_definitions/v1.0/ I did it, but not sure if it is necessary
  • check with status command in MAVProxy console if you can see your message ID and the value you setted. You can also display in real time your data with module load graph and graph YOUR_MSG_ID.NAME_VARIABLE. If it’s working, go to MP side!

Mission Planner side:

  • Follow the instruction to install mission planner
  • Modify the file MissionPlanner\ExtLibs\Mavlink\message_definitions\common.xml with your new message (has to be the same than ArduPilot side)
  • Install python 2.7 for Windows and run MissionPlanner\ExtLibs\Mavlink\regenerate.bat from Windows and not cygwin or cmd prompt. Make sure you added the C:\Python27 to your PATH before. It will generate a new Mavlink.cs with your message ID
  • Build and run MP. A good way to check if your message is received, press ctrl+F in MP and click “MAV Link” button and see if your message is there.

Done !

1 Like

@Katawan I am really glad it helped you!
I am planning to write a tutorial for programming communication protocol via UART for ArduPilot, it should contain this topic too. But I need to do pull request first and be 100% sure that all I’ve done is working.

1 Like