Sending MAVProxy messages from a python program?

Ah. I’m going untethered and I want it to lock onto headings at various times. I wrote a simple P controller to listen for yaw in the mavlink messages and then used the pwm to simulate joystick, but this seems a little clunky.

Sounds like I can put it in auto mode and then try?

Check the MAV_CMD_CONDITION_YAW for that, in python should be something like:

master.mav.command_long_send(
    master.target_system,
    master.target_component,
    mavutil.mavlink.MAV_CMD_CONDITION_YAW,
    0,
    90, 5, 1, 0, 0, 0, 0)

Besides that, the auto mode will only work with a connected position system.

Ah, so I tried that command, but it seems like there’s two reasons it didn’t work?

  1. I wasn’t in auto mode
  2. I didn’t have a connected positioning system.

Does that sound right?

I don’t have a positioning system underwater, but for what I need, I only need to control Yaw underwater. Is there some way to fake positioning system so that I can use the yaw built into pixhawk?

Yes, this python code will only work with guided and auto modes.
You’ll need to send a manual control to perform what you need, probably in stabilize mode.

Check our pymavlink examples, that @jwalser posted here.

To help you, it’s possible to get the yaw and the yaw velocity with the message ATTITUDE.

yaw_msg = master.recv_match(type='ATTITUDE', blocking=True).to_dict()
print(yaw_msg['yaw'], yaw_msg['yawspeed'])

About your controller, try to add a small integrator to help you with the error.

This can make your ROV to go away, because it’ll think that the position is correct all the time.

Great, thanks!

What are the ways I can get the Blue ROV into Auto or Guided mode?

For example, I saw a Mavlink message where I could tell the vehicle its position. Is that one of the ways that might work?

But, from what you said below about my ROV going away…

  • It seems that in auto mode, it will try to hold position and even if I’m only trying to control heading, it will still drift since it’s not getting a position update.

Correct?

I wonder if I keep telling the ROV that it’s current position is it’s actual position, so that it doesn’t think it’s drifting?

My problem with the manual mode is that the update rate of receiving messages to control on seemed sporadic / slow.

I guess I could always add a compass to the RPi, but that takes functionality away from the Pixhawk, which doesn’t seem like the best option.

The only way possible is if the ROV have a GPS fix, take a look here about the modes that need a GPS fix, some do not exist in ArduSub, like Guided_NoGPS.

Yes, you can try to send a GPS message like this one:

    master.mav.gps_raw_int_send(
        0,                     # time_usec                 : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t)
        3,                     # fix_type                  : See the GPS_FIX_TYPE enum. (uint8_t)
        lat,                   # lat                       : Latitude (WGS84), in degrees * 1E7 (int32_t)
        lon,                   # lon                       : Longitude (WGS84), in degrees * 1E7 (int32_t)
        0,                     # alt                       : Altitude (AMSL, NOT WGS84), in meters * 1000 (positive for up). Note that virtually all GPS modules provide the AMSL altitude in addition to the WGS84 altitude. (int32_t)
        0,                     # eph                       : GPS HDOP horizontal dilution of position (unitless). If unknown, set to: UINT16_MAX (uint16_t)
        0,                     # epv                       : GPS VDOP vertical dilution of position (unitless). If unknown, set to: UINT16_MAX (uint16_t)
        0,                     # vel                       : GPS ground speed (m/s * 100). If unknown, set to: UINT16_MAX (uint16_t)
        0,                     # cog                       : Course over ground (NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. If unknown, set to: UINT16_MAX (uint16_t)
        6                      # satellites_visible        : Number of satellites visible. If unknown, set to 255 (uint8_t)
    )

@jwalser have more experience with this, maybe he can figure out a way to use a “fake GPS” without problems.

You can control the frequency, like described here.

If your goal is to hold a specific heading, the solution is not auto mode. You should try stabilize mode or depth hold modes, the autopilot runs it’s own pid controller to maintain the heading in those stabilized modes. Your program can give yaw input until the heading is where you want it, then just set the input to zero (the input is the desired rate of rotation), and the autopilot will take care of holding its current heading.

Thanks Jacob. Yeah that’s what I was hoping was to have the autopilot do it’s own PID over me doing it on the RPi.

So do you have the Mavlink command handy to do that?

There’s no mavlink command, the autopilot will just hold it’s current heading when the input rate is zero. Use the MANUAL_CONTROL command to emulate pilot input.

I see, so I would still have to make my own PID to control that. If I’m setting a rate and not a heading, then it will probably oscillate without some sort of PID to slow the yaw rate down as it gets close to my desired heading value.

So in case it helps, my needed mission is to have the ROV underwater, untethered, doing the example mission below.

  • Hold depth at 50 feet
  • 0 degrees for 60 seconds.
  • 90 degrees for 60 seconds.
  • 180 degrees for 60 seconds.
  • 270 degrees for 60 seconds.
  • Surface
  • Move to a new GPS location at surface
  • Repeat above

I have already untethered it, installed WiFi, and have done PID control on RPi to command the MANUAL_CONTROL Mavlink messaged based on the master.recv_match to lock onto a heading

The MANUAL_CONTROL just seems kind of clunky and I’d like to have all PID reside within the Autopilot and just send it desired depth and desired heading (aka yaw) commands over having to read the messages and compute my own PID to command the MANUAL_CONTROL.

Also, thanks, this forum is very helpful.

Hi,

I tried to send GPS using the below, but it still says no GPS fix and won’t going into AUTO mode. Any thoughts?

master.mav.gps_raw_int_send(
0, # time_usec : Timestamp (microseconds since UNIX epoch or microseconds since system boot) (uint64_t)
3, # fix_type : See the GPS_FIX_TYPE enum. (uint8_t)
lat, # lat : Latitude (WGS84), in degrees * 1E7 (int32_t)
lon, # lon : Longitude (WGS84), in degrees * 1E7 (int32_t)
0, # alt : Altitude (AMSL, NOT WGS84), in meters * 1000 (positive for up). Note that virtually all GPS modules provide the AMSL altitude in addition to the WGS84 altitude. (int32_t)
0, # eph : GPS HDOP horizontal dilution of position (unitless). If unknown, set to: UINT16_MAX (uint16_t)
0, # epv : GPS VDOP vertical dilution of position (unitless). If unknown, set to: UINT16_MAX (uint16_t)
0, # vel : GPS ground speed (m/s * 100). If unknown, set to: UINT16_MAX (uint16_t)
0, # cog : Course over ground (NOT heading, but direction of movement) in degrees * 100, 0.0…359.99 degrees. If unknown, set to: UINT16_MAX (uint16_t)
6 # satellites_visible : Number of satellites visible. If unknown, set to 255 (uint8_t)
)

Hi Mike,

@jwalser is correct, you should considerer his comment.
Sorry about that.

But, it’s possible to set a position via mavproxy with GPSInput module or GPS_INPUT message.

  1. Start mavproxy with --load-module='GPSInput' or send module load GPSInput in the cli (command line interface).
  2. Set GPS_TYPE to MAV in QGC or param set GPS_TYPE 14 in mavproxy (necessary for GPSInput module and GPS_INPUT message).
  3. Run this python script.

You’ll be able to check the mavlink console (--console) that the GPSInput is working, and after that it’ll be possible to set the vehicle in guided mode.

Screenshot%20from%202018-03-22%2009-58-38

But as said before, this approach is not recommended.

1 Like

Hi. I want to know the meanings of COMMAND_ACK.result. As I know:
0 - is success
1 - ?
2 - ?
3 - unsopported command
4 - fail ???
How can I get more detailed info after sending a command ?

Hi,

You can check the mavlink documentation about COMMAND_ACK structure, the result field is a enum called MAV_RESULT

| 0 | MAV_RESULT_ACCEPTED             | Command ACCEPTED and EXECUTED     |
| 1 | MAV_RESULT_TEMPORARILY_REJECTED | Command TEMPORARY REJECTED/DENIED |
| 2 | MAV_RESULT_DENIED               | Command PERMANENTLY DENIED        |
| 3 | MAV_RESULT_UNSUPPORTED          | Command UNKNOWN/UNSUPPORTED       |
| 4 | MAV_RESULT_FAILED               | Command executed, but failed      |
| 5 | MAV_RESULT_IN_PROGRESS          | WIP: Command being executed       |

Thanks a lot.
I have one more question. We want to test a gimbal camera control without any mission (we are using PX4 firmware and DroneCore as a mavlink library). We know that we can control servo using DO_SET_SERVO command. But this command is not supported with PX4. Can you offer other way to test gimbal control without mission (without arming etc. directly) ?

DO_SET_SERVO will work for unassigned servo outputs. If you have configured a camera gimbal mount and assigned pan/tilt functions to servo outputs then you can use the MAV_CMD_DO_MOUNT_CONTROL command.

PX4 supports this command, but the problem is - this command does not affect if there is no mission. For ex. if we run sample take_off mission - it will work, otherwise - not. We want to test only gimbal, camera control without arming and etc. Is it possible ?

It’s possible with ArduSub and ardupilot firmware in the way that I described. I don’t know anything about PX4 firmware.

Ok, I will try. Thank you for support !

1 Like