I'm trying to use dynmsg_demo as a library to convert ROS messages to YAML and then convert that YAML back to a ROS message. However, it seems that the conversion is not symmetric: we can't convert a ROS message to YAML using message_to_yaml() and then convert that same YAML (string) back to a ROS message using yaml_to_rosmsg().
Example:
#include <iostream>
#include "dynmsg_demo/message_reading.hpp"
#include "dynmsg_demo/msg_parser.hpp"
#include "dynmsg_demo/typesupport_utils.hpp"
#include "std_msgs/msg/string.h"
#include <yaml-cpp/yaml.h>
int main()
{
// Start with a ROS message, like a std_msgs/String
std_msgs__msg__String msg{
{
"hello world",
11,
12
},
};
// Convert it to a YAML representation
InterfaceTypeName interface{"std_msgs", "String"};
RosMessage ros_msg;
ros_msg.type_info = get_type_info(interface);
ros_msg.data = reinterpret_cast<uint8_t *>(&msg);
YAML::Node yaml_msg = message_to_yaml(ros_msg);
std::cout << "message to YAML:" << std::endl;
std::cout << yaml_msg << std::endl << std::endl;
// Convert the YAML representation back to a ROS message
YAML::Emitter emitter;
emitter << YAML::DoubleQuoted << YAML::Flow << yaml_msg;
std::cout << "YAML:" << std::endl;
std::cout << emitter.c_str() << std::endl << std::endl;
// What we want
// RosMessage ros_msg_from_yaml = yaml_to_rosmsg(interface, emitter.c_str());
// ..which is
// RosMessage ros_msg_from_yaml = yaml_to_rosmsg(interface, "{\"data\": {\"type\": \"string\", \"value\": \"hello world\"}}");
// What yaml_to_rosmsg() expects
RosMessage ros_msg_from_yaml = yaml_to_rosmsg(interface, "{\"data\": \"hello world\"}");
// Show ROS message
std_msgs__msg__String * msg_from_yaml = reinterpret_cast<std_msgs__msg__String *>(ros_msg_from_yaml.data);
rosidl_runtime_c__String msg_from_yaml_str = msg_from_yaml->data;
std::cout << msg_from_yaml_str.data << std::endl;
return 0;
}
The output is:
message to YAML:
data:
type: string
value: hello world
YAML:
{"data": {"type": "string", "value": "hello world"}}
hello world
Using RosMessage ros_msg_from_yaml = yaml_to_rosmsg(interface, emitter.c_str()); results in a parsing exception.
message_to_yaml() converts the message into a YAML representation that includes type information, but yaml_to_rosmsg() converts a different kind of YAML representation (something similar to what ros2 topic echo or rosidl_generator_traits::to_yaml() would output) to a message.
I'm trying to use
dynmsg_demo
as a library to convert ROS messages to YAML and then convert that YAML back to a ROS message. However, it seems that the conversion is not symmetric: we can't convert a ROS message to YAML usingmessage_to_yaml()
and then convert that same YAML (string) back to a ROS message usingyaml_to_rosmsg()
.Example:
The output is:
Using
RosMessage ros_msg_from_yaml = yaml_to_rosmsg(interface, emitter.c_str());
results in a parsing exception.message_to_yaml()
converts the message into a YAML representation that includes type information, butyaml_to_rosmsg()
converts a different kind of YAML representation (something similar to whatros2 topic echo
orrosidl_generator_traits::to_yaml()
would output) to a message.Is this correct, or am I missing something? It's not really what I expected (after reading "It can go both directions" here https://discourse.ros.org/t/ros2-c-based-dynamic-typesupport-example/19079/3), but looking at the tests, this is the correct behaviour.
I modified
message_to_yaml()
so that the generated YAML matches whatyaml_to_rosmsg()
expects, but I'm just wondering if there is a reason for this.