Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic Message Deserialization #2260

Open
wew84 opened this issue Aug 2, 2023 · 4 comments
Open

Dynamic Message Deserialization #2260

wew84 opened this issue Aug 2, 2023 · 4 comments
Labels
more-information-needed Further information is required

Comments

@wew84
Copy link

wew84 commented Aug 2, 2023

Hi,

I'm relatively new to the rclcpp client after several years of using rclpy and both ROS1 clients. I'm trying to deserialize a message dynamically at runtime. I have the following callback for a generic subscriber:

[this, topic_name, topic_type](const std::shared_ptr<rclcpp::SerializedMessage> &message) {
    std::shared_ptr<rcpputils::SharedLibrary> library = rclcpp::get_typesupport_library(topic_type, "rosidl_typesupport_cpp");
    const rosidl_message_type_support_t * message_type_support = rclcpp::get_typesupport_handle(topic_type, "rosidl_typesupport_cpp", *library);
    auto members = static_cast<const rosidl_typesupport_introspection_cpp::MessageMembers *>(message_type_support->data);
    rcutils_allocator_t allocator = rcutils_get_default_allocator();
    auto data = allocator.allocate(members->size_of_, allocator.state);
    if (nullptr == data) {
        RCLCPP_ERROR(this->get_logger(), "Could not allocate message memory %zu", members->size_of_);
        return;
    }
    rclcpp::SerializationBase ser(message_type_support);
    ser.deserialize_message(message.get(), data);
...

When I run this, I get a members->size_of_ of 140737332973024, so I assume the casting to message members is incorrect.
I also tried the init_function() in members.

I may be misunderstanding the mechanism for introspection or the serialization API. Any help would be great. Thanks.

@wew84 wew84 changed the title RCLCPP Dynamic Message Deserialization Dynamic Message Deserialization Aug 2, 2023
@wew84
Copy link
Author

wew84 commented Aug 2, 2023

After some further investigation, it looks like the cast to members always returns junk.

  • Operating System:
    Ubuntu 22.04.2 LTS
  • Installation type:
    Binaries
  • Version or commit hash:
    16.0.5-2jammy.20230721.204813
  • DDS implementation:
    N/A (Fast-RTPS)
  • Client library (if applicable):
    rclcpp

Steps to reproduce issue

I wrote this code sample.

#include "rclcpp/rclcpp.hpp"
#include "rosidl_typesupport_introspection_cpp/message_introspection.hpp"


int main(int argc, char * argv[])
{
    std::string topic_type = "std_msgs/msg/String";
    std::shared_ptr<rcpputils::SharedLibrary> library = rclcpp::get_typesupport_library(topic_type, "rosidl_typesupport_cpp");
    const rosidl_message_type_support_t * message_type_support = rclcpp::get_typesupport_handle(topic_type, "rosidl_typesupport_cpp", *library);
    auto members = static_cast<const rosidl_typesupport_introspection_cpp::MessageMembers *>(message_type_support->data);
}

When I bring up a debugger, I get the following output:
image

(I also tested with can_msgs/msg/Frame):
image

It seems that the cast should be valid if I correctly understand the IDL generators here.

If this is more relevant in the IDL repo, I'd be happy to move it there.

@clalancette
Copy link
Contributor

So I don't know about the exact code you are using above. But we do have examples of using serialized messages and successfully decoding. One such example is in https://github.com/ros2/demos/blob/rolling/demo_nodes_cpp/src/topics/listener_serialized_message.cpp .

More specifically, rosbag2 implements exactly the kind of message-agnostic thing you are trying to do here. So it may be worthwhile to look at how that is implemented, maybe starting with https://github.com/ros2/rosbag2/blob/rolling/rosbag2_cpp/src/rosbag2_cpp/types/introspection_message.cpp .

Let me know if that helps at all.

@clalancette clalancette added the more-information-needed Further information is required label Aug 10, 2023
@doruktiktiklar
Copy link

Hi, I also have a similar problem. I want to write a collector application that output a JSON object periodically. That json object will include a list of items. Each item will include 3 things: the name of the topic, the type of the topic and the deserialized last message in that topic.

This is close to what I want to do, but it does not provide a parse method
https://github.com/RobotWebTools/rosbridge_suite/blob/ros2/rosapi/src/rosapi/objectutils.py

Rosbag2 seem to just put the serialized message inside their own serialized message
https://github.com/ros2/rosbag2/blob/rolling/rosbag2_cpp/src/rosbag2_cpp/writer.cpp#L202

I guess dynamic deserialization is what I need, but it is not implemented
ros2/ros2#1374
eProsima/Fast-DDS#3296
https://github.com/ros2/rclcpp/blob/rolling/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_serialization_support.cpp

Is it possible to do what I want? I would prefer using C++ or python. It probably is possible with C but I am not sure about which way to go.

@Barry-Xu-2018
Copy link
Collaborator

@doruktiktiklar

Your ideas are similar to the current service event. Please refer to https://github.com/ros-infrastructure/rep/blob/336d3b66135ca71a82d5e903de1e865e4ceddd2d/rep-2012.rst#service-event-definition. request and response part are deserialized data.
About parse method, you can refer to the implementation of player_service_client.cpp. e.g. https://github.com/ros2/rosbag2/blob/0b6a8dacef1a7de0117a48502c987209830f5e96/rosbag2_transport/src/rosbag2_transport/player_service_client.cpp#L32-L97

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
more-information-needed Further information is required
Projects
None yet
Development

No branches or pull requests

4 participants