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

Is it possible to switch topic message type with code?

asked 2022-08-01 08:42:07 -0500

gustav gravatar image

Hi!

In my ros project I will have a constant flow of information from node A to node B. Node A will tell node B to start up / shut down certain modes via service calls and then feed it with data for that specific mode via a topic. Only one mode will be running at a specific time in node B, but they all require different kinds of data. Adapting the custom message type to one mode will therefore not suit the other modes, since they might require e.g. a string instead of two integers. Having one topic for each node with its specific message type will just be a bad idea since there will be only one "actively used" topic at one time, and lots of unused? So I'm wondering if it's possible to change the message type of a topic in the code so that the program can switch message type depending on what mode is running. I also thought about having a message type that fits all of the different modes, sort of finding the least common denominator, but that will just end up with it always being bigger than it needs to be.

Any advice?

Thanks in advance!

edit retag flag offensive close merge delete

Comments

Hi, I think you can try to customize your own message type, like

uint8 whichModeNow
uint8 modeA_data
string modeB_data

By doing so, you don't need to change the topic message type in the runtime.

RyanChen.YLC gravatar image RyanChen.YLC  ( 2022-08-01 19:18:24 -0500 )edit

@RyanChen.YLC Thanks for the answer! However, I think you missunderstood me. I don't want to use one type of message, since it would have to be able to acommodate every modes' needed variables. That would be fine in your example since each mode only needs one variable each, but my modes will require much more data per message. Adding them all up to one message would make it difficult, since that kind of message would become massive, which isn't preferrable. I would like to have several different message types like:

ModeAmsg:

int32 speed
uint16 turning
...

ModeBmsg:

string message
bool statement
...

And then I would like to be able to have one topic that changes its message type between ModeAmsg, ModeBmsg, ModeCmsg etc depending on what mode is running.

gustav gravatar image gustav  ( 2022-08-04 06:55:19 -0500 )edit

2 Answers

Sort by » oldest newest most voted
0

answered 2022-08-09 18:36:36 -0500

ChuiV gravatar image

While probably not recommended, it is possible to have multiple types on the same topic. Given types A and B, you can make an A publisher to /data, and a B publisher to /data. An A subscriber to /data will only get A-typed data, while a B subscriber to /data will only get B-typed data.. But at this point, you might as well just put them on separate topics to help make other tools happy (ie rosbag2 doesn't like it when you have multiple types in one topic. At least last I checked.)

If you're concerned about resources, you could create and destroy your publishers/subscribers as needed based on your mode. If you're in mode mode_A, make sure your B publisher (or subscriber) is destroyed, then create your A publisher. Remember that for each mode change, each node will have to re-do endpoint discovery on the RTPS layer. Again, some tools (like rosbag2) may not appreciate topic types changing dynamically like this.

Bottom line, I think that unless you REALLY have to, I'd recommend to keep topic types constant, and make new topics for different types.

edit flag offensive delete link more
0

answered 2022-08-10 02:31:59 -0500

ljaniec gravatar image

I think you are interested in a so-called generic subscriber in ROS2, with deserialization of its messages as needed.

Recently I saw this package:

that could be helpful, with other links mentioned in its README:

To parse any ROS message at runtime, it requires:

  • The name of the type (for instance "sensors_msgs/JointState")
  • The definition of the type (for instance this one),
  • The raw memory buffer to be deserialized into individual key/values pairs.

The raw memory buffer is usually obtained by:

edit flag offensive delete link more

Comments

1

The GenericSubscriber still requires you to give the type name as a string. Then you can deserialize the message in the callback using the rclcpp::Serialization<MsgType> class:

#include <rclcpp/rclcpp.hpp>
#include <rclcpp/serialization.hpp>
#include <std_msgs/msg/string.hpp>

void cb(const std::shared_ptr<rclcpp::SerializedMessage> msg)
{
    rclcpp::Serialization<std_msgs::msg::String> ser;
    std_msgs::msg::String ros_msg;
    ser.deserialize_message(msg.get(), &ros_msg);
    std::cout << "Got: " << ros_msg.data << std::endl;
}

int main(int argc, char ** argv)
{
    rclcpp::init(argc, argv);
    auto node = rclcpp::Node::make_shared("deserialization");

    auto sub = node->create_generic_subscription("/chatter", "std_msgs/String", 10, &cb);
    rclcpp::spin(node);
    rclcpp::shutdown();
    return EXIT_SUCCESS;
}

No need for an external package.

ChuiV gravatar image ChuiV  ( 2022-08-10 08:43:52 -0500 )edit

@ChuiV Nice, it seems easier this way, thank you

ljaniec gravatar image ljaniec  ( 2022-08-10 08:59:46 -0500 )edit

Question Tools

2 followers

Stats

Asked: 2022-08-01 08:42:07 -0500

Seen: 487 times

Last updated: Aug 10 '22