DFKI-NI / rospy_message_converter

Converts between Python dictionaries and JSON to ROS messages.
BSD 3-Clause "New" or "Revised" License
226 stars 101 forks source link

No way to send dictionary which doesn't have 'data' as a key #66

Closed gaspersavle closed 1 year ago

gaspersavle commented 1 year ago

If for example i want to publish a dictionary with integer keys it wouldn't let me do it, so i changed the keys to strings but it literally won't accept anything other than having 'data' as a key which kind of defeats the purpose in my opinion.

The dictionary i want to send:

self.cornerDict = {
    1: None,
    2: None,
    3: None,
    4: None,
    5: None,
    6: None,
    7: None,
    8: None}

Would be nice if you could send nested dictionaries too, like this one:

self.pandaPose1 = {
    0: {'POS': None,
        'PROX': {'head': None, 'L_shoulder': None, 'R_shoulder': None, 'L_elbow': None, 'R_elbow': None, 'L_wrist': None, 'R_wrist': None}},
    1: {'POS': None,
        'PROX': {'head': None, 'L_shoulder': None, 'R_shoulder': None, 'L_elbow': None, 'R_elbow': None, 'L_wrist': None, 'R_wrist': None}},
    2: {'POS': None,
        'PROX': {'head': None, 'L_shoulder': None, 'R_shoulder': None, 'L_elbow': None, 'R_elbow': None, 'L_wrist': None, 'R_wrist': None}}, 
    3: {'POS': None,
        'PROX': {'head': None, 'L_shoulder': None, 'R_shoulder': None, 'L_elbow': None, 'R_elbow': None, 'L_wrist': None, 'R_wrist': None}}, 
    4: {'POS': None,
        'PROX': {'head': None, 'L_shoulder': None, 'R_shoulder': None, 'L_elbow': None, 'R_elbow': None, 'L_wrist': None, 'R_wrist': None}}, 
    5: {'POS': None,
        'PROX': {'head': None, 'L_shoulder': None, 'R_shoulder': None, 'L_elbow': None, 'R_elbow': None, 'L_wrist': None, 'R_wrist': None}},
    6: {'POS': None,
        'PROX': {'head': None, 'L_shoulder': None, 'R_shoulder': None, 'L_elbow': None, 'R_elbow': None, 'L_wrist': None, 'R_wrist': None}}, 
    7: {'POS': None,
        'PROX': {'head': None, 'L_shoulder': None, 'R_shoulder': None, 'L_elbow': None, 'R_elbow': None, 'L_wrist': None, 'R_wrist': None}},
    8: {'POS': None,
        'PROX': {'head': None, 'L_shoulder': None, 'R_shoulder': None, 'L_elbow': None, 'R_elbow': None, 'L_wrist': None, 'R_wrist': None}},
        } 
mintar commented 1 year ago

This repository converts between Python dictionaries and ROS messages, so first you need to define a ROS message that holds your data. ROS messages cannot have integer field names, so this would not work:

Corners.msg

float64 1
float64 2
float64 3
float64 4
float64 5
float64 6
float64 7
float64 8

During compilation, you would get: genmsg.base.InvalidMsgSpec: 1 is not a legal message field name.

This has nothing to do with this repo, but with ROS messages.


For your example, the following would work:

PandaPoses.msg

# would be better to use PandaPose[] here, or PandaPose[8]
PandaPose pose1
PandaPose pose2
PandaPose pose3
PandaPose pose4
PandaPose pose5
PandaPose pose6
PandaPose pose7
PandaPose pose8

PandaPose.msg

float64 pos   # or whatever type you want `pos` to be
PandaJointStates prox

PandaJointStates.msg

float64 head
float64 l_shoulder   # note that all field names should be lower case, so l_shoulder, not L_shoulder
float64 r_shoulder
float64 l_elbow
float64 r_elbow
float64 l_wrist
float64 r_wrist

Then you can do this:

from rospy_message_converter import message_converter
dictionary = {
    'pose1': {
        'pos': 1.0,
        'prox': {
            'head': 1.0,
            'l_shoulder': 2.0,
            'r_shoulder': 3.0,
            'l_elbow': None,
            'r_elbow': None,
            'l_wrist': None,
            'r_wrist': None,
        },
    },
    'pose2': {
        'pos': 1.0,
        'prox': {
            'head': 1.0,
            'l_shoulder': 2.0,
            'r_shoulder': 3.0,
            'l_elbow': None,
            'r_elbow': None,
            'l_wrist': None,
            'r_wrist': None,
        },
    },
}
message = message_converter.convert_dictionary_to_ros_message('your_ros_message_package_here/PandaPoses', dictionary)

Note that there is nothing special about the field name data, and in my messages above I didn't use it.

However, in your use case, I strongly suggest looking at using sensor_msgs/JointStates. It's best to use standard ROS messages wherever possible.

mintar commented 1 year ago

By the way, this is what the message would look like as a list:

PandaPoses.msg

PandaPose[] poses

... and then:

from rospy_message_converter import message_converter

dictionary = {
    'poses': [
        {
            'pos': 1.0,
            'prox': {
                'head': 1.0,
                'l_shoulder': 2.0,
                'r_shoulder': 3.0,
                'l_elbow': None,
                'r_elbow': None,
                'l_wrist': None,
                'r_wrist': None,
            },
        },
        {
            'pos': 1.0,
            'prox': {
                'head': 1.0,
                'l_shoulder': 2.0,
                'r_shoulder': 3.0,
                'l_elbow': None,
                'r_elbow': None,
                'l_wrist': None,
                'r_wrist': None,
            },
        },
    ]
}
message = message_converter.convert_dictionary_to_ros_message('your_ros_message_package_here/PandaPoses', dictionary)