Robotics StackExchange | Archived questions

How can I access all msg fields recursively in a message_generator?

Hallo,

I am trying to create a messagegenerator. For this purpose I need to access all message fields recursively until I reach the level of pure primitive types (for which I have basic templates). What I would like to do is to process all fields in a msggen.MsgSpec.parsedfields() and for each of them that is not "isbuiltin" I would like to get the corresponding msggen.MsgSpec class and go on in a recursive way. Does this make sense? How can I do this? Another possibility that I explored would be to use rosmsg.getmsg_text on the non-primitive types but this seems more complicated since I have to parse the message description myself. Thanks for your help.

Riccardo

Asked by Riccardo on 2014-04-13 23:11:25 UTC

Comments

Answers

after struggling for 2 days I found a solution (maybe) defining this method

def get_children_spec(base_type, search_path):
    (package, name) = genmsg.names.package_resource_name(base_type)
    tmp_msg_context = genmsg.msg_loader.MsgContext.create_default()
    spec_temp = genmsg.msg_loader.load_msg_by_type(tmp_msg_context, '%s/%s' %(package, name), search_path)  
    return spec_temp

I would be curious to know if there is a better solution but for the moment I am happy with this.

Asked by Riccardo on 2014-04-14 04:46:10 UTC

Comments

You might not need to iterate the msg fields recursively in the first place. It should be sufficient to iterate only the fields of the current message and for non-builtin field type invoke the serialization / deserialization function of the sub message (rather then implement it again within this message). At least that is the way gencpp, genpy and genlisp deal with it.

Update:

Pointing you to code might not be the best help since the message generator code / templates are everything but easy to read. You could look at the gencpp and genpy packages though.

What I am referring to is the following idea: for each built-in type you will have e.g. a serialize function:

serialize(bool)
serialize(int)

When you now want to serialize a Message Foo you will serialize all of its members like this:

serialize(Foo) {
    serialize(my_bool_member)
    serialize(my_int_member)
}

For a nested message you also only care about its member and not about their recursive fields because you will delegate the serialization of sub messages to there existing serialize implementation:

serialize(Bar) {
    serialize(my_foo_member)
    serialize(my_other_foo_member)
}

Asked by Dirk Thomas on 2014-04-14 07:25:03 UTC

Comments

Hi Dirk. Thanks for the reply. Sorry but I am not quite sure that I understand how your solution should work. Can you please give me more details or point me to some documentation? I would really appreciate that. Thanks.

Asked by Riccardo on 2014-04-25 05:18:11 UTC

I'm not exactly sure what you're trying to accomplish but I'd like to propose to take a look at the built-in "dir()" function in python. For example:

>>> from sensor_msgs.msg import LaserScan
>>> dir(LaserScan)
['__class__', '__delattr__', '__doc__', '__eq__', '__format__', '__getattribute__', '__getstate__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '_check_types', '_connection_header', '_full_text', '_get_types', '_has_header', '_md5sum', '_slot_types', '_type', 'angle_increment', 'angle_max', 'angle_min', 'deserialize', 'deserialize_numpy', 'header', 'intensities', 'range_max', 'range_min', 'ranges', 'scan_time', 'serialize', 'serialize_numpy', 'time_increment']

This would give you the ability to "access all message fields recursively".

Asked by pierrelux on 2014-04-30 18:48:44 UTC

Comments