ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

What's the best way to convert a ros message to a string or xml?

asked 2011-06-20 05:41:57 -0600

pparescasellas gravatar image

updated 2011-06-20 05:44:49 -0600

Hey everybody,

I would like to know what's the best way (if possible) to convert any message in ros into something similar to xml or just a string. Let's say I have this message defined:

float64[6] a
float64[]  b
int32      c

I'd like to parse it to something like:

  <a type="float64" value="1.0,2.0,3.0,4.0,5.0,6.0"/>
  <b type="float64" value="7.0,5.0,6.0"/>
  <c type="int32" value="4"/>

What's the best way to achieve that? I want it to be the most generic possible (so, I don't want to manually put my message.a, message.b, message.c into a string). I'm going to use this into some kind of listener node subscribed to many topics so I don't want to define one callback for each topic and having to unpack manually each message.

Edit: I have been hinted somewhere else to use Python to achieve this because it's easier. I'd like a C++ solution but if that's too hard then I'd appreciate someone explaining how can I easily parse ros messages in python to know all the names, values and types in a somewhat dynamic way.

Thanks a lot!

edit retag flag offensive close merge delete


Similar to - the suggestion there is to use rosbag api.

lucasw gravatar image lucasw  ( 2016-02-08 13:59:55 -0600 )edit

4 Answers

Sort by ยป oldest newest most voted

answered 2011-06-20 06:28:11 -0600

Lorenz gravatar image

updated 2011-06-21 21:12:27 -0600

In C++ you don't have introspection for messages, i.e. you need to know the message types at compile time. In theory, it would be possible to deserialize messages into something dynamic such as a stl map over strings and boost::any or something but I don't know of any implementation.

Python is much easier because it's a dynamic language. You can import messages at run-time and you can introspect instances of any class at run-time. Consider the following example:

import roslib; roslib.load_manifest('geometry_msgs')
import geometry_msgs.msg

p = geometry_msgs.msg.Vector3(1, 2, 3)
print p.__slots__
print p._slot_types
print p.__getattribute__('x')

It shows how to list all slots, i.e. member variables of a ros message, how to get the types of all slots and how to get the value of a slot. With that it should be pretty easy to write something generic to create an xml representation of messages.

edit flag offensive delete link more


Thanks for the answer! It seems a lot easier using python, I'll try what you suggest :)
pparescasellas gravatar image pparescasellas  ( 2011-06-20 20:19:11 -0600 )edit
Ok I have a rospy node running and listening to topics. Once I receive one of them only p.__slots__ works; I get errors for the other two: AttributeError: 'Vector3' object has no attribute '__get_attribute__' and the same for '__slot_types'. Is the example you posted working to you? :)
pparescasellas gravatar image pparescasellas  ( 2011-06-21 05:07:42 -0600 )edit
They're misspelled: __getattribute__ and _slot_types is what you want. I suggest using a python interpreter such as Ipython, which will allow you to use tab completion to list methods on objects.
bhaskara gravatar image bhaskara  ( 2011-06-21 05:51:04 -0600 )edit
Thanks, I just got it working checking dir( data ); I saw that they were misspelled there :). I'm using eclipse's python plug-in and it seems to have a hard time auto-completing sometimes.
pparescasellas gravatar image pparescasellas  ( 2011-06-21 06:05:39 -0600 )edit
Sorry for that. I updated my answer accordingly.
Lorenz gravatar image Lorenz  ( 2011-06-21 21:12:53 -0600 )edit
Also, in python, if you use str(msg) on your message this will give you the YAML representation,
Dimitar Simeonov gravatar image Dimitar Simeonov  ( 2011-06-22 00:49:22 -0600 )edit

answered 2011-07-11 10:05:56 -0600

bsatzinger gravatar image

Hi, heres a python function which will convert a ros message object into an xml representation. It needs to be modified if you want to use a message with arrays, but it'll work for nested structures just fine.

def ros2xml(msg, name, depth=0):
xml = "";
tabs = "\t"*depth

if hasattr(msg, "_type"):
    type = msg._type
    xml = xml + tabs + "<" + name + " type=\"" + type + "\">\n"

        for slot in msg.__slots__:
            xml = xml + ros2xml(getattr(msg, slot), slot, depth=depth+1)
        xml = xml + tabs + str(msg)
    xml = xml + tabs + "</" + name + ">\n"
    xml = xml + tabs + "<" + name + ">" + str(msg) + "</" + name + ">\n"
return xml
edit flag offensive delete link more


That's great mate, thank you! But I already coded something similar; when I decided to go with python all became clear and easy :)
pparescasellas gravatar image pparescasellas  ( 2011-08-08 20:59:50 -0600 )edit

answered 2011-08-25 04:42:07 -0600

joq gravatar image

Running rostopic echo will output messages in YAML format.

If YAML is not adequate, there must be tools for converting it into XML, etc.

edit flag offensive delete link more

answered 2011-06-20 05:56:25 -0600

AFAIK there's not easy way. (But someone more knowledgeable than I might know)

"[H]ow can I easily parse ros messages in python to know all the names, values and types in a somewhat dynamic way."

You should probably be able to follow the code path of deserialize. Since deserialze needs to do all the things you're doing, you should (<-dangerous word here) be able to use the same way to get what you want.

edit flag offensive delete link more


I have been trying to serialize the messages using ros::serialize and then trying to deserialize them again manually (so, byte by byte). I thought this would be possible because I had the output of __getMessageDefinition() (which is deprecated by the way). This method returns the .msg definition
pparescasellas gravatar image pparescasellas  ( 2011-06-20 20:22:01 -0600 )edit
And with the .msg definition I know how many bytes I should read to rebuild the first parameter etc. this was great until I realized that there are some definitions that do not specify vectors length so.. how was I supposed to know where the next variable begins? At that point I came here to ask :)
pparescasellas gravatar image pparescasellas  ( 2011-06-20 20:27:13 -0600 )edit
For vectors of unspecified length, the first four bytes are parsed as an int that specifies the length.
bhaskara gravatar image bhaskara  ( 2011-06-21 05:56:04 -0600 )edit
Also, if this is a useful feature to you, it might be good to bring it up on the ros-developers mailing list. This kind of thing is difficult to do in roscpp right now, but it might be made easier, e.g., by adding some additional utility functions to the generated header files of the messages analogous to the Python ones.
bhaskara gravatar image bhaskara  ( 2011-06-21 06:02:49 -0600 )edit
Oh great! I didn't know the first four bytes were the vectors' length. Thanks a lot, I might use this instead of doing all the parsing with python (but I've already started and it's working so... not sure what I'll do). Thanks again!
pparescasellas gravatar image pparescasellas  ( 2011-06-21 06:07:52 -0600 )edit

Question Tools



Asked: 2011-06-20 05:41:57 -0600

Seen: 13,917 times

Last updated: Aug 25 '11