Type Adapter cannot convert one RosMsg to another RosMsg
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 805
- Forks
- 564
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 27
Description
Bug report
Required Info:
- Operating System:
- Ubuntu 22.04 + VMware
- Installation type:
- source build
- Version or commit hash:
- humble
- DDS implementation:
- Fast-RTPS and Eclipse Cyclone DDS
- Client library (if applicable):
- rclcpp
Steps to reproduce issue
# TestMsg.msg
uint32 id
uint64 time
// rosAdapter.hpp
#ifndef ROS_ADAPTER_HPP
#define ROS_ADAPTER_HPP
#include <string>
#include <iostream>
#include "rclcpp/type_adapter.hpp"
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/byte_multi_array.hpp"
#include "std_msgs/msg/header.hpp"
#include "tutorial_interfaces/msg/test_msg.hpp"
#define ROS_TYPE
#ifdef ROS_TYPE
// fail
using MsgT = tutorial_interfaces::msg::TestMsg;
#else
// work fine
using MsgT = std::string;
#endif // ROS_TYPE
template <>
struct rclcpp::TypeAdapter<MsgT, std_msgs::msg::ByteMultiArray>
{
using is_specialized = std::true_type;
using custom_type = MsgT;
using ros_message_type = std_msgs::msg::ByteMultiArray;
static void
convert_to_ros_message(
const custom_type &source,
ros_message_type &destination)
{
std::cout << "convert_to_ros_message!!!" << std::endl;
#ifdef ROS_TYPE
destination.data.resize(12);
destination.data[0] = source.id;
destination.data[1] = source.time;
#else
destination.data.resize(source.size());
memcpy(destination.data.data(), source.data(), source.size());
#endif
}
static void
convert_to_custom(
const ros_message_type &source,
custom_type &destination)
{
std::cout << "convert_to_custom!!!" << std::endl;
#ifdef ROS_TYPE
std::cout << "source size = " << source.data.size() << std::endl;
destination.id = source.data[0];
std::cout << "destination.id = " << destination.id << std::endl;
destination.time = source.data[4];
#else
destination.resize(source.data.size());
memcpy(destination.data(), source.data.data(), source.data.size());
#endif
}
};
RCLCPP_USING_CUSTOM_TYPE_AS_ROS_MESSAGE_TYPE(MsgT, std_msgs::msg::ByteMultiArray);
#endif // ROS_ADAPTER_HPP
// pub.cpp
#include <chrono>
#include <memory>
#include <string>
#include "rclcpp/rclcpp.hpp"
#include "rosAdapter.hpp"
using namespace std::chrono_literals;
class MinimalPublisher : public rclcpp::Node
{
public:
MinimalPublisher()
: Node("minimal_publisher"), count_(0)
{
auto timer_callback =
[this]() -> void
{
#ifdef ROS_TYPE
MsgT msg;
msg.id = this->count_++;
msg.time = 0x12345678;
#else
MsgT msg = "my name!";
#endif
this->publisher_->publish(msg);
};
publisher_ = this->create_publisher<MsgT>("topic", 10);
timer_ = create_wall_timer(30ms, timer_callback);
}
private:
rclcpp::TimerBase::SharedPtr timer_;
rclcpp::Publisher<MsgT>::SharedPtr publisher_;
size_t count_;
};
int main(int argc, char *argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalPublisher>());
rclcpp::shutdown();
return 0;
}
// sub.cpp
#include <memory>
#include "rclcpp/rclcpp.hpp"
#include <chrono>
#include "rosAdapter.hpp"
class MinimalSubscriber : public rclcpp::Node
{
public:
MinimalSubscriber()
: Node("minimal_subscriber")
{
auto callback = [this](const MsgT &msg)
{
#ifdef ROS_TYPE
std::cout << "msg.id = " << msg.id << std::endl;
std::cout << "msg.time = " << msg.time << std::endl;
#else
std::cout << "msg = " << msg << std::endl;
#endif
};
subscription_ = this->create_subscription<MsgT>("topic", 10, callback);
}
private:
rclcpp::Subscription<MsgT>::SharedPtr subscription_;
};
int main(int argc, char *argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalSubscriber>());
rclcpp::shutdown();
return 0;
}
Expected behavior
The subscriber (sub.cpp) can output the message.
Actual behavior
A segmentation fault occurs because the subscriber receives zero data when calling the convert_to_custom function in TypeAdapter.
$ ros2 run topics sub
convert_to_custom!!!
source size = 0
[ros2run]: Segmentation fault
From the above-presented result, the subscriber enters the convert_to_custom function with a data size of zero. Consequently, the subscriber is unable to switch the ros_message_type to the custom_type (which is another RosMsg Type).
Additional information
It appears that TypeAdapter is unable to convert one RosMsg Type to another RosMsg Type.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the TypeAdapter specialization in rosAdapter.hpp and reproduce the failure using pub.cpp and sub.cpp on the stated Humble source build. Inspect why convert_to_custom receives an empty ByteMultiArray when adapting tutorial_interfaces::msg::TestMsg, and consider the issue done when the subscriber receives the published fields without a segmentation fault.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- robotics
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100