Sending MAVProxy messages from a python program?

So I can send commands to my ROV from the MAVProxy command line on my topside computer… Can I send commands to this link from a python program rather than from the command line? The hope is to send a sequence of commands like arming the vehicle, loading WPs, changing the flight mode, etc.

Thanks!

1 Like

Yes! Here I arm the vehicle, wait 2 seconds, then disarm the vehicle.

import time
from pymavlink import mavutil

mavutil.set_dialect("ardupilotmega")

autopilot = mavutil.mavlink_connection('udpin:192.168.2.1:14550')

msg = None

# wait for autopilot connection
while msg is None:
        msg = autopilot.recv_msg()

print msg

# The values of these heartbeat fields is not really important here
# I just used the same numbers that QGC uses
# It is standard practice for any system communicating via mavlink emit the HEARTBEAT message at 1Hz! Your autopilot may not behave the way you want otherwise!
autopilot.mav.heartbeat_send(
6, # type
8, # autopilot
192, # base_mode
0, # custom_mode
4, # system_status
3  # mavlink_version
)

autopilot.mav.command_long_send(
1, # autopilot system id
1, # autopilot component id
400, # command id, ARM/DISARM
0, # confirmation
1, # arm!
0,0,0,0,0,0 # unused parameters for this command
)

time.sleep(2)

autopilot.mav.command_long_send(
1, # autopilot system id
1, # autopilot component id
400, # command id, ARM/DISARM
0, # confirmation
0, # disarm!
0,0,0,0,0,0 # unused parameters for this command
)
1 Like

Thanks Jacob, this is just what I was looking for!

When I run this code, I see the following message appear in my MAVProxy console:
Got MAVLink msg: COMMAND_ACK {command : 400, result : 0}

This message appears only once. Is this expected? I see that “result : 0” means the command was accepted/executed but was expecting to see a notification for each sent message.

It is only sent in response to COMMAND_LONG messages. You should see it twice, once for arm, once for disarm.

Hi Jacob,

I’m trying to send a waypoint to the rov using mavlink, so I created another function in the example code you gave me. I referenced this link for the command sequence.

#mavwp set-up
wp = mavwp.MAVWPLoader()

def set_waypoint_cmd_mavwp(lat,lon,alt):
    wp.add(mavutil.mavlink.MAVLink_mission_item_message(
        1,#sys id
        1,#component id
        0,#seq wp id
        0,#frame id
        16,#mav_cmd 
        0,#current, true/false
        0,#auto continue
        0,0,0,0,#params 1-4: hold time(s),acceptable radius(m), pass/orbit,yaw angle
        lat,lon,alt) #lat/lon/alt
    )

    print "#of waypoints=",wp.count(),"\n"
    print "waypoint is=",wp.wp(0),"\n"
    autopilot.waypoint_clear_all_send()
    autopilot.waypoint_count_send(wp.count())
    msg = autopilot.recv_match(type=['MISSION_REQUEST'],blocking=True)
    print msg
    seq=0
    autopilot.mav.send(wp.wp(msg.seq))

then I call my function with the following arguments:
set_waypoint_cmd_mavwp(39.003981, -76.244854,0)

$ python wpsend_test2.py
#of waypoints= 1

waypoint is= MISSION_ITEM {target_system : 1, target_component : 1, seq : 0, frame : 0, command : 16, current : 0, autocontinue : 0, param1 : 0, param2 : 0, param3 : 0, param4 : 0, x : 39.003981, y : -76.244854, z : 0}

MISSION_REQUEST {target_system : 255, target_component : 0, seq : 0}

And on the MAVProxy terminal I see the following messages pop up:

Got MAVLink msg: MISSION_ACK {target_system : 255, target_component : 0, type : 0}
APM: Flight plan received

But when I check the WP list through MAVProxy, I see my home position listed as a wp and nothing about the point i just sent:

wp list
MANUAL> Requesting 1 waypoints t=Wed Sep 27 14:06:56 2017 now=Wed Sep 27 14:06:56 2017
16 0 39.0066337585 -76.4080886841 0.000000 p1=0.0 p2=0.0 p3=0.0 p4=0.0 cur=0 auto=1
Saved 1 waypoints to way.txt
Saved waypoints to way.txt

Then in QGC, I see the following “error” message:

If i set up a WP in QGC, I see it on wp list after clicking the “upload” button. Any idea what I’m missing? I also tried sending the waypoint using the mission_item and mission_item_int message types to mirror how we send the arm/disarm commands (which work independently–haven’t figured out how to get them to work one after another with a sleep in between…)

Thanks,
Stephanie

Stephanie, I recommend you start with the mavproxy waypoint module gui: wp editor

You will need to dig into ardusub source code to find out what is happening otherwise (as would I). I can take a look at this next week if you are still struggling.

The QGC error pops up because it got an ack from the autopilot for a command that QGC did not send (unexpected).

Thanks. Using wp editor helped! Looks like home position wants to be the initial WP, so I just have to add my WPs after the home position. This will work fine for my application.

Now I am having issues changing flight modes via mavlink. Using the “command_long” message again, now with MAV_CMD #176 (do_set_mode), I see the following error:

Got MAVLink msg: COMMAND_ACK {command : 176, result : 3}

meaning unsupported/unknown command. Has anyone else had success updating the mode via mavlink? I also tried the SET_MODE message type although the comment in the source code says this message type is outdated. SET_MODE failed with “result : 4”

p.s. I am able to change the flight mode via MAVProxy command line

I’m able to use a pymavlink function to change modes:

mavutil.mavfile.set_mode(autopilot,mode_mapping_sub,0,0)

where mode_mapping_sub = 0 for stabilize, 19 for manual, etc…

@jwalser, can you give an example of how to send commands to the motors?

for example, to dive to a certain depth, should I use the RC_CHANNELS_OVERRIDE message to send values to channels 5 and 6? Or should I try to send MANUAL_CONTROL messages like QGC?

You are confusing input channels and output channels. Those mavlink messages control input channels, so you would want to write to channel 3 (throttle). Either message should work, but I recommend manual_control.

https://www.ardusub.com/operators-manual/rc-input-and-output.html

Hi all!
I was reading this post and I try test the next after arm the ROV:

# MAV_CMD_DO_SET_SERVO inside of MAV_CMD
master.mav.command_long_send(
1,
1,
183,
0,
1,
1400, 0, 0, 0, 0, 0
)

and I see that the QGC show this message:

Set servo command failed

Then I test change the mode Manual, Stabilize, etc…

**# MAV_CMD_DO_SET_MODE inside of MAV_CMD **
master.mav.command_long_send(
1,
1,
176,
0,
1, # I change this with 0,19, 10 and always have the same output
0, 0, 0, 0, 0, 0
)

And I receive this output:

Set Flight mode command not supported

So, What is wrong with this?
And also, what is the difference between MAVLink Type Enumerations and MAVLink Messages?

MAVLink Type Enumerations have many sub titles and the ID is not unique, for example, between MAV_SENSOR_ORIENTATION and MAV_CMD.
What is the idea general? To know how choose one or other and the functions of pymavlink to execute one or other.

Finally, you recommend use the manual_control, and this command belong to MAV_CMD,
I can use this command with command_long_send?
For example:

master.mav.command_long_send(
1,
1,
manual_control, # or 69
0,
1,
0, 0, 0, 0, 0, 0
)

But, this have this parameters:
target,
x,
y,
z,
r,
buttons

Then, I have very confused about how use your suggest.
Greetings!

You can not put a setpoint on motor channels. Only non-motor channels are allowed with this command.

It’s not supported. Use SET_MODE.

An enumeration is a list of possible options, states, related things. The mavlink message spec will tell you when the items from a particular enumeration are to be used as a parameter to the command.

Here is an example of how to use it:

    def set_mode(self, mode):
        """ Set ROV mode
            http://ardupilot.org/copter/docs/flight-modes.html
        Args:
            mode (str): MAVLink mode
        Returns:
            TYPE: Description
        """
        mode = mode.upper()
        if mode not in self.conn.mode_mapping():
            print('Unknown mode : {}'.format(mode))
            print('Try:', list(self.conn.mode_mapping().keys()))
            return
        mode_id = self.conn.mode_mapping()[mode]
        self.conn.set_mode(mode_id)

And a list with all modes.

2 Likes

Similar to above,
How mavproxy command " rc 5 1600" can be implemented in Python i.e to move BlueRov2 forward at 1600 PWM, until commanded to stop.
Python implementation of depth hold of say 1 meter would be highly appreciated.

Hi @sjpanwar,

This will show how you can use mavproxy with any mavlink command.

If you don’t know how to use it, check this python script.

[quote=“sjpanwar, post:14, topic:1515”]
Thanks for response
Is it possible for you send a python script to move BlueROV in forward direction for say 3 seconds and then stop.

Hi @sjpanwar,

You can use the mavlink message RC_CHANNELS_OVERRIDE to send a forward message, you can check this line to see an example.

It is possible to provide python command line, in running a python script
Rpi of Blue ROV2, to

  1. To capture image and video from camera connected to Rpi
  2. To rotate camera servo motor, possiblly through manual mavlink command
    or any other command

Hi @sjpanwar. It is possible to do all of these things that you describe, but we cannot write your programs for you.

Please read more about ardusub, mavlink, pymavlink and mavproxy. All of the information that you need is online. If you have more specific questions or need to know where to find certain information, we can help you. There is also a developer chat that you are welcome to join.

Here are some examples with pymavlink: Pymavlink · GitBook