@@ -51,24 +51,7 @@ class RosTopicSubNode : public BT::ConditionNode
5151protected:
5252 struct SubscriberInstance
5353 {
54- void init (std::shared_ptr<rclcpp::Node> node, const std::string& topic_name)
55- {
56- // create a callback group for this particular instance
57- callback_group = node->create_callback_group (
58- rclcpp::CallbackGroupType::MutuallyExclusive, false );
59- callback_group_executor.add_callback_group (callback_group,
60- node->get_node_base_interface ());
61-
62- rclcpp::SubscriptionOptions option;
63- option.callback_group = callback_group;
64-
65- // The callback will broadcast to all the instances of RosTopicSubNode<T>
66- auto callback = [this ](const std::shared_ptr<TopicT> msg) {
67- last_msg = msg;
68- broadcaster (msg);
69- };
70- subscriber = node->create_subscription <TopicT>(topic_name, 1 , callback, option);
71- }
54+ SubscriberInstance (std::shared_ptr<rclcpp::Node> node, const std::string& topic_name);
7255
7356 std::shared_ptr<Subscriber> subscriber;
7457 rclcpp::CallbackGroup::SharedPtr callback_group;
@@ -83,12 +66,13 @@ class RosTopicSubNode : public BT::ConditionNode
8366 return sub_mutex;
8467 }
8568
69+ using SubscribersRegistry =
70+ std::unordered_map<std::string, std::weak_ptr<SubscriberInstance>>;
71+
8672 // contains the fully-qualified name of the node and the name of the topic
87- static std::unordered_map<std::string, std::shared_ptr<SubscriberInstance>>&
88- getRegistry ()
73+ static SubscribersRegistry& getRegistry ()
8974 {
90- static std::unordered_map<std::string, std::shared_ptr<SubscriberInstance>>
91- subscribers_registry;
75+ static SubscribersRegistry subscribers_registry;
9276 return subscribers_registry;
9377 }
9478
@@ -108,7 +92,7 @@ class RosTopicSubNode : public BT::ConditionNode
10892 /* * You are not supposed to instantiate this class directly, the factory will do it.
10993 * To register this class into the factory, use:
11094 *
111- * RegisterRosAction<DerivedClasss >(factory, params)
95+ * RegisterRosAction<DerivedClass >(factory, params)
11296 *
11397 * Note that if the external_action_client is not set, the constructor will build its own.
11498 * */
@@ -118,22 +102,6 @@ class RosTopicSubNode : public BT::ConditionNode
118102 virtual ~RosTopicSubNode ()
119103 {
120104 signal_connection_.disconnect ();
121- // remove the subscribers from the static registry when the ALL the
122- // instances of RosTopicSubNode are destroyed (i.e., the tree is destroyed)
123- if (sub_instance_)
124- {
125- sub_instance_.reset ();
126- std::unique_lock lk (registryMutex ());
127- auto & registry = getRegistry ();
128- auto it = registry.find (subscriber_key_);
129- // when the reference count is 1, means that the only instance is owned by the
130- // registry itself. Delete it
131- if (it != registry.end () && it->second .use_count () <= 1 )
132- {
133- registry.erase (it);
134- RCLCPP_INFO (logger (), " Remove subscriber [%s]" , topic_name_.c_str ());
135- }
136- }
137105 }
138106
139107 /* *
@@ -190,6 +158,26 @@ class RosTopicSubNode : public BT::ConditionNode
190158// ----------------------------------------------------------------
191159// ---------------------- DEFINITIONS -----------------------------
192160// ----------------------------------------------------------------
161+ template <class T >
162+ inline RosTopicSubNode<T>::SubscriberInstance::SubscriberInstance(
163+ std::shared_ptr<rclcpp::Node> node, const std::string& topic_name)
164+ {
165+ // create a callback group for this particular instance
166+ callback_group =
167+ node->create_callback_group (rclcpp::CallbackGroupType::MutuallyExclusive, false );
168+ callback_group_executor.add_callback_group (callback_group,
169+ node->get_node_base_interface ());
170+
171+ rclcpp::SubscriptionOptions option;
172+ option.callback_group = callback_group;
173+
174+ // The callback will broadcast to all the instances of RosTopicSubNode<T>
175+ auto callback = [this ](const std::shared_ptr<T> msg) {
176+ last_msg = msg;
177+ broadcaster (msg);
178+ };
179+ subscriber = node->create_subscription <T>(topic_name, 1 , callback, option);
180+ }
193181
194182template <class T >
195183inline RosTopicSubNode<T>::RosTopicSubNode(const std::string& instance_name,
@@ -262,17 +250,15 @@ inline bool RosTopicSubNode<T>::createSubscriber(const std::string& topic_name)
262250 auto it = registry.find (subscriber_key_);
263251 if (it == registry.end ())
264252 {
265- it = registry.insert ({ subscriber_key_, std::make_shared<SubscriberInstance>() })
266- .first ;
267- sub_instance_ = it->second ;
268- sub_instance_->init (node_, topic_name);
253+ sub_instance_ = std::make_shared<SubscriberInstance>(node_, topic_name);
254+ registry.insert ({ subscriber_key_, sub_instance_ });
269255
270256 RCLCPP_INFO (logger (), " Node [%s] created Subscriber to topic [%s]" , name ().c_str (),
271257 topic_name.c_str ());
272258 }
273259 else
274260 {
275- sub_instance_ = it->second ;
261+ sub_instance_ = it->second . lock () ;
276262 }
277263
278264 // Check if there was a message received before the creation of this subscriber action
0 commit comments