0
$\begingroup$

Rosanswers logo

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.

$\endgroup$

2 Answers 2

1
$\begingroup$

Rosanswers logo

It appears that RVIZ properly unsubscribes when displays are disabled by simply calling reset() on the Subscription shared_ptr. I confirmed this checking that the subscriber count falls when using "ros2 topic info".

With regards to the weak_ptrs piling up - it looks like every time you add a new timer, service, or subscription to a callback group it will remove any weak_ptrs that are expired


Originally posted by fergs with karma: 13902 on 2020-08-18

This answer was NOT ACCEPTED on the original site

Post score: 2

$\endgroup$
0
$\begingroup$

Rosanswers logo

It looks like this simply doesn't exist yet. This appears to be confirmed by this TODO in image_common. rclcpp does not yet support it but, I think, even lower, the rmws don't get support it (couldn't find any reference in Cyclone or FastRTPS). You'll want to start by getting the RMW vendors to support it first (I think).


Originally posted by Josh Whitley with karma: 1766 on 2020-08-04

This answer was NOT ACCEPTED on the original site

Post score: 3


Original comments

Comment by fergs on 2020-08-18:
That comment might be out of date (I've fixed other things like this recently that were out of date because the port was done quite a while ago). For reference, RVIZ actually does disconnect from the topic when you disable a display (confirmed using ros2 topic info and seeing that the subscriber count falls back to 0). From what I can see, RVIZ displays simply reset the shared_ptr to the subscriber. It is possible the weak_ptrs are still piling up though...

Comment by Josh Whitley on 2020-08-18:
Thanks for the clarification. Do you have a link to somewhere in the RViz code that this happens? I'll update my answer with the link and suggestion.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.