0
$\begingroup$

Rosanswers logo

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:

<message>
  <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"/>
</message>

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!


Originally posted by pparescasellas on ROS Answers with karma: 95 on 2011-06-20

Post score: 7


Original comments

Comment by lucasw on 2016-02-08:
Similar to http://answers.ros.org/question/11289/read-or-write-message-fromto-file/ - the suggestion there is to use rosbag api.

$\endgroup$

3 Answers 3

0
$\begingroup$

Rosanswers logo

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.


Originally posted by Lorenz with karma: 22731 on 2011-06-20

This answer was ACCEPTED on the original site

Post score: 7


Original comments

Comment by Dimitar Simeonov on 2011-06-22:
Also, in python, if you use str(msg) on your message this will give you the YAML representation,

Comment by Lorenz on 2011-06-21:
Sorry for that. I updated my answer accordingly.

Comment by pparescasellas on 2011-06-21:
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.

Comment by bhaskara on 2011-06-21:
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.

Comment by pparescasellas on 2011-06-21:
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? :)

Comment by pparescasellas on 2011-06-20:
Thanks for the answer! It seems a lot easier using python, I'll try what you suggest :)

$\endgroup$
0
$\begingroup$

Rosanswers logo

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"
    
    try:
        for slot in msg.__slots__:
            xml = xml + ros2xml(getattr(msg, slot), slot, depth=depth+1)
    except:
        xml = xml + tabs + str(msg)
    xml = xml + tabs + "</" + name + ">\n"
else:
    xml = xml + tabs + "<" + name + ">" + str(msg) + "</" + name + ">\n"
return xml

Originally posted by bsatzinger with karma: 76 on 2011-07-11

This answer was NOT ACCEPTED on the original site

Post score: 3


Original comments

Comment by pparescasellas on 2011-08-08:
That's great mate, thank you! But I already coded something similar; when I decided to go with python all became clear and easy :)

$\endgroup$
0
$\begingroup$

Rosanswers logo

Running rostopic echo will output messages in YAML format.

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


Originally posted by joq with karma: 25443 on 2011-08-25

This answer was NOT ACCEPTED on the original site

Post score: 1

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.