How to pass complex arguments to rostopic (Python subprocess)?
I want to call ros_comm
tools (mainly rostopic
to publish messages right now) via Python subprocess
and pass complex YAML arguments (nested, containing message fields of all field types, etc.) to it.
Let's say I want to publish messages of type geometry_msgs/PointStamped
$ rosmsg show geometry_msgs/PointStamped
std_msgs/Header header
uint32 seq
time stamp
string frame_id
geometry_msgs/Point point
float64 x
float64 y
float64 z
on a topic /pt
using explicit YAML dictionary syntax like described in the wiki section "4.3 Command-line and messages (dictionaries)" which would be called on the command line like follows:
rostopic pub pt geometry_msgs/PointStamped '{header: {stamp: now, frame_id: base_link}, point: {x: 1.0, y: 2.0, z: 3.0}}'
Using the YAML list syntax works well but is not really convenient to work with and is limited to easier cases I guess:
import subprocess
yaml_list_header = '[0, now, base_link]'
yaml_list_point = '[1.0, 2.0, 3.0]'
sp = subprocess.Popen(['rostopic', 'pub', 'pt', 'geometry_msgs/PointStamped', yaml_list_header, yaml_list_point, '-r', '2'])
EDIT: Probably not obvious... nesting with YAML list syntax is possible as well.
import subprocess
yaml_list_header = '[0, [0, 0], base_link]'
yaml_list_point = '[1.0, 2.0, 3.0]'
sp = subprocess.Popen(['rostopic', 'pub', 'pt', 'geometry_msgs/PointStamped', yaml_list_header, yaml_list_point, '-r', '2'])
What's the best approach (most flexible, least error prone) to publish messages via rostopic
called via Python subprocess
? It is probably best to pass the cmd
as list to subprocess.Popen(cmd)
. (Not to use shlex.split(<cmd-as-string>)
to generate cmd
for subprocess.Popen(cmd)
due to little control about what the result looks like and if it suites the syntax.) (As YAML is a valid super-set of JSON it's probably possible to use some string to JSON parser for conversion.)
I'm not sure it's a best practice (I dislike using the command line tools from Python/C++ in any case), but what about using the regular msg classes, populate their fields, serialise to yaml and pass that string to
rostopic pub
?I dislike using the command line tools as well. However for now it is the best approach to get fast results. " serialise to yaml and pass that string to rostopic pub?" That's exactly what I don't know how to do in detail yet.