Mavros: Play a tune via MAVCMD

Created on 10 Jun 2019  ·  15Comments  ·  Source: mavlink/mavros

I'm trying to play a tune via rosrun command:
rosrun mavros mavcmd 258 0 0 0 0 0 0 0

anybody knows which params i need to send?


MAVROS version and platform

ROS: Melodic
Ubuntu: 16.04

Autopilot type and version

[ ] ArduPilot
[ x] PX4

Version: 3.7.1

question

All 15 comments

MAV_CMD doesn't have such command.

If you want to send PLAY_TUNE, then you have to write a plugin.

Beginner question: now that the plugin exists (see this pull request - thanks @mortenfyhn) what would be the most straightforward way to play a simple tune via mavros?

I am on ROS noetic, Ubuntu 20.04, ArduSub 4.0.2 on Pixhawk1. Buzzer is connected and plays something when the pixhawk starts up. But I can't get it to play anything after that.

I have tried
roslaunch mavros apm.launch fcu_url:=udp://:[email protected]:14549
and when I do
rostopic echo /mavros/state
it shows regular messages, so I am fairly confident the connection worked.
However, when I try
rostopic pub -1 /mavros/play_tune mavros_msgs/PlayTuneV2 "format: 2 tune: '>e16e8e16r16c16e8g4<g4'"
nothing happens.

I feel like I am missing a crucial basic step. Any pointer into the right direction would be appreciated. I am still learning.

No worries, what you're missing might just be to enable the play_tune plugin. When you launch mavros, do you get a long list of plugins saying plugin loaded / blacklisted / similar? It tells you which plugins are enabled. You can add the play_tune plugin to the config file apm_pluginlists.yaml which is read by apm.launch. Hopefully that solves it.

Thank you for your fast reply!

Yep, I get
[ INFO] [1620733606.153262125]: Plugin play_tune loaded
[ INFO] [1620733606.155413105]: Plugin play_tune initialized

apm_pluginlists.yaml looks like this:

plugin_blacklist:
# common
- actuator_control
- ftp
- safety_area
- hil
# extras
- altitude
- debug_value
- image_pub
- px4flow
- vibration
- vision_speed_estimate
- wheel_odometry

plugin_whitelist: []
#- 'sys_*'

That's odd. Do you have QGroundControl or something similar running? You can use its "mavlink inspector" to check if you're seeing mavlink PLAY_TUNE_V2 message. Beyond that I think the other maintainers might be better suited to figure this out.

Oh, interesting, it doesn't show up in QGC.

qgc_mavlink_messages

Looks like I will first need to figure out what's going wrong here. Maybe it's an issue with ArduSub.

Oh and thank you very much for your time :-)

It might be so that it won't show up in QGC even when it works, when I think about it. The message might go straight to the pixhawk, and the pixhawk might not pass it on to QGC.

@mortenfyhn PLAY_TUNE goes strait to FCU link, so it's unlikely to see it on GCS, except if the firmware routes it back.
Unfortunately it's not easy to capture that message in mavros v1, only if you put something between FCU and MAVROS to catch packets.

Hmm, you could try to build Wireshark plugin to inspect data (but i don't really know is it still working or not).
And since we are dealing with opensource firmware, we could go and see whether ArduSub accepts that message or not :)

Interesting to know, thank you for investigating!

Is there a (beginner-friendly) way to circumvent this issue?
Can I help with anything and where would be the most effective place to make the change?

I can probably extend the plugin to support plain PLAY_TUNE messages. @vooon, what's the policy for API changes? I'm tempted to create a new subscriber, so the plugin reads ~play_tune for mavros_msgs/PlayTune -> mavlink PLAY_TUNE, and ~play_tune_v2 for mavros_msgs/PlayTuneV2 -> mavlink PLAY_TUNE_V2. But that will break the old API, which uses ~play_tune for v2 messages.

Alternatively I can add a parameter that determines if it expects v1 or v2 messages on ~play_tune, and I'll output the matching mavlink message.

@mortenfyhn since we at 1.0 stage, i'd prefer to keep existing api.
Also user shouldn't care about witch version of message is sent, so i'd prefer to add param plus detection.

Something like that:

void connection_cb() {
  int new_ver = 0
  if (nh.getParam("message_version", new_ver) {
    // check 1 vs 2
  } 
  if (new_ver == 0) {
    new_ver = m_uas->is_ardupilotmega() ? 1 : 2;
  }

  message_version = new_ver;
}

@mortenfyhn since we at 1.0 stage, i'd prefer to keep existing api.

:+1:

I'll do roughly as you suggest:

  • Add a parameter.
  • If unset, keep existing behaviour.
  • If set to specify v1/v2, use that.
  • If unset, and m_uas->is_ardupilotmega() == true, then use v1.

Yes, also i think it's ok to use 0 == auto (v1 for APM / v2 for others).

Ah, also, we should simply convert PlayTuneV2.msg to PLAY_TUNE.
Need to check that format == MML (APM's implementation), then do something like that (pseudocode):
```
PLAY_TUNE pt{};

mavlink::set_string(pt.tune, tune->tune);
mavlink::set_string_z(pt.tune2, tune->tune[pt.tune.size():]);
``

Was this page helpful?
0 / 5 - 0 ratings