[ros2] Issue with subscribing to topic using SingleThreadedExecutor and Node in ROS2.
hi all,
The code below seems to work well as I expected, but it doesn't.
class MyClass : public rclcpp::Node
{
public:
MyClass()
: Node("my_class")
{
subscription_ = this->create_subscription<std_msgs::msg::String>(
"test", 10, std::bind(&MyClass::MyCallback, this, _1));
}
private:
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
void MyCallback(const std_msgs::msg::String::SharedPtr msg) const
{
RCLCPP_INFO(rclcpp::get_logger("MyClass"), "Subscribed : '%s'", msg->data.c_str());
}
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
/*
// work well
rclcpp::executors::SingleThreadedExecutor single_exec;
auto a = std::make_shared<MyClass>();
single_exec.add_node(a);
single_exec.spin();
// work well
rclcpp::spin(std::make_shared<MyClass>());
*/
// not work
rclcpp::executors::SingleThreadedExecutor single_exec;
single_exec.add_node(std::make_shared<MyClass>());
single_exec.spin();
rclcpp::shutdown();
return 0;
}
The MyClass is derived from rclcpp::Node, and the shared pointer is implicitly convertible to a shared pointer to rclcpp::Node. The addnode function in the executor takes a shared pointer to rclcpp::Node, so the call to addnode should succeed. However, when I run the code upper, it doesn't subscribe to the topic and can't be found on the ros2 node list command; it just blocks.
If I replace the executor code with either of the ones in the comments, it works well.
Asked by leeminju531 on 2023-04-05 04:57:15 UTC
Answers
When you created a shared_ptr node as you did in the commented code, it exists in "main" scope. On the other hand, when you just create the node as input argument, it will not be available outside of single_exec.add_node
.
Since rclcpp::executors::SingleThreadedExecutor
inherits from rclcpp::executor::Executor
(link to doc), it also offers APIs tsuch as remove_node
, so I guess the shared pointer to a rclcpp::Node cannot just got removed after calling add_node
.
I would go with the first "work well".
Asked by GuimingChen on 2023-04-06 08:39:42 UTC
Comments
Thank you for your comments. Both add_node
and rclcpp::spin
take the same shared_ptr
as an input parameter, which was initially confusing to me.
The rclcpp::spin()
function takes ownership of the shared_ptr
and keeps it alive for the duration of the spin loop. However, single_exec.add_node(std::make_shared<MyClass>())
creates a shared_ptr
to a MyClass
instance, but that shared_ptr
is not held onto by anything outside of the add_node()
function call, as you mentioned earlier. As a result, the MyClass
instance is immediately destroyed after the call to add_node()
, and the subscription is lost (it looks like it takes a weak_ptr).
Thanks a lot!
Asked by leeminju531 on 2023-04-06 10:07:46 UTC
Comments