0
$\begingroup$

I have a map plugin I've made for rqt_gui that I am going to be using to visualize location information from n number of ROVs/autonomous vehicles. So far I am able to find and create subscribers to get the ROV's NavSatFix message based on the different topic names that contain NavSatFix messages. Since the total amount of subscribers needs to adjust dynamically the total amount of subscribers can increase or decrease. My solution is to create a std::map of subscribers, using the following definition.

std::map<std::string, rclcpp::Subscription<sensor_msgs::msg::NavSatFix>::SharedPtr> nav_sat_subscribers_;

Currently this works fine and I can create n number of subscribers with the Node::Subscription object mapped to the topic name. I have a separate script that creates a node with a specified number of publishers to various NavSatFix topics.

The issue I am having is whenever I try to refresh this information in the event a topic is no longer being published to. First I remove the icons and their associated information in the map, then I use the Subscription::reset() function to remove the subscription (this seems to be the only way to kill a subscriber without killing the node)

    void MapPlugin::clearGpsTopics()
    {
        for (const auto& entry : nav_sat_subscribers_){
         auto node_name = entry.first;
         nav_sat_subscribers_[node_name].reset();

         //code that removes map icons
         }
        nav_sat_subscribers_.clear();
    }

The problem I run into is whenever I try to clear and refresh the subscriber map. If I clear the subscribers, then kill the publisher node, everything works fine, the subscribers release and the topics go out of scope. If I kill the publisher node then clear the subscribers the subscription doesn't seem to clear and the topic persists. I don't know why the subscriber fails to release if the topic is no longer being published to so any insight or alternative to the way I am doing this would be appreciated.

I'll also include the following code which is the function that creates the subscribers in case that provides any insight. (I have to use the binded_function in order to pass an additional argument to the callback function, in case that seems odd)

void MapPlugin::createROVSubscription(const std::string& topic_name) 
{
    std::function<void(const sensor_msgs::msg::NavSatFix::SharedPtr msg)> binded_function = std::bind(&MarblePlugin::GpsCallback, this, std::placeholders::_1, topic_name);
    nav_sat_subscribers_[topic_name] = subscriber_node_->create_subscription<sensor_msgs::msg::NavSatFix>(topic_name, 1000, binded_function);
}
$\endgroup$

1 Answer 1

0
$\begingroup$

I found at least a work around to this problem, I don't know if it is how rqt's executors work, but it seems that if the topic isn't being published to and the subscriber is released, it won't actually go out of scope until another message is published to that topic. Now when I reset the shared pointer, I immediately create a blank message and a publisher to the topic, publish a single message and when those go out of scope the topic does as well.

  nav_sat_subscribers_[node_name].reset();
  auto message = std::make_shared<sensor_msgs::msg::NavSatFix>();
  auto publisher = node_->create_publisher<sensor_msgs::msg::NavSatFix>(node_name.c_str(), 1);
  publisher->publish(*message);

Kind of a stupid work around, but in case anyone runs into a similar issue this could be their fix.

$\endgroup$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.