Hi, I'm trying to implement a dynamic subscribing behaviour to a ros2 node. When a topic becomes obsolete for the node I would like it to unsubscribe from that topic. How could this be accomplished?
The object the node is holding is a rclcpp::Subscription
which is created by its parents method create_subscription
(https://docs.ros.org/en/rolling/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html)
Any suggestion would be appreciated, if I have overlooked some documentation please point me to it.
I have had a look at the innerworkings of the Node. The callback group keeps a weak_ptr to every subcriptions ever added to the group. Now I didnt find any routine removing them from the vector, if they are not used anymore. Of course its not piling on a huge memory load with the objects them self being deleted. But running my node for a while the vector just keeps growing, never removing the weak_ptr from the vector.
Originally posted by vale on ROS Answers with karma: 71 on 2020-06-12
Post score: 7
Original comments
Comment by Solrac3589 on 2020-06-19:
Have been checking and is quite curious there is no specific function for that (at least i didn't found it neither)!
I'm thinking that maybe you could call the destructor inherited for the SubscriptionBase (http://docs.ros2.org/beta2/api/rclcpp/classrclcpp_1_1subscription_1_1Subscription.html) . this way maybe it works!
Comment by vale on 2020-06-26:
I have tried this in the meantime. When the rclcpp::Subscription::SharedPtr
is not referenced anymore the callback function doesnt get called by messages to the topic anymore. But the entry in the callback group does not get removed. I cant find any way to remove the subscription from the CallbackGroup either, that could be triggered by the code inside the node (http://docs.ros2.org/dashing/api/rclcpp/classrclcpp_1_1callback__group_1_1CallbackGroup.html)
Comment by Orhan on 2020-07-18:
This is interesting but I unfortunately don't have an environment to test it. I believe what you want is achievable by using
NodeTopics::add_subscription(
rclcpp::SubscriptionBase::SharedPtr subscription,
rclcpp::CallbackGroup::SharedPtr callback_group)
function instead of create_subscription
. I might have checked the source code very badly but did you try digging add_subscription()
one? There are test codes in the rclcpp repo for reference of usage.
Comment by TheBee on 2020-08-12:
Hey there!
Did you manage to stop/deactivate/shut down your subscriber without shutting down the entire node? I´m working with eloquent and to be honest I dont know how to unreference the Subscription Shared Pointer...
Let´s say my subscriber looks like this:
m_camera_info_sub = this->create_subscription<sensor_msgs::msg::CameraInfo>("/img_topic", 1, std::bind(&CameraAdapter::cbCameraImage, this, _1));
I get the camera info once, then i never need it again so in Ros1 I would do
m_camera_info_sub.shutdown();
But what can I do in Ros2 to achieve this?
EDIT: m_camera_info_sub.reset() seems to do the trick! Only briefly tested this so there might be something I´m missing but so far it´s looking good!
Comment by vale on 2020-08-13:
So you call reset()
on your Subscription? I was not able to find that function in the documentation or the class definition of the Subscription.
Comment by gvdhoorn on 2020-08-13:
reset()
is likely a method of the SharedPtr
, not of the subscription object itself. It essentially releases the pointed-to, which results in it going out-of-scope, leading to destruction.
Comment by doisyg on 2020-08-13:
In my experience, reset() seems to work, i.e the callback is not served anymore. Is it safe to use as a ROS1 shutdown() replacement ? Is there any risk of memory leakage in case of frequent subscription/ reset cycles ?
Comment by vale on 2020-08-13:
Thanks, you are right. I did delete the object a different way but that works as well. I am not sure though if the DDS layer is still receiving the multicast messages, after the deleting the Subscription.
And for sure it does not change the fact that weak pointers keep piling up in the callbackgroup.