@@ -51,24 +51,7 @@ class RosTopicSubNode : public BT::ConditionNode
51
51
protected:
52
52
struct SubscriberInstance
53
53
{
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);
72
55
73
56
std::shared_ptr<Subscriber> subscriber;
74
57
rclcpp::CallbackGroup::SharedPtr callback_group;
@@ -83,12 +66,13 @@ class RosTopicSubNode : public BT::ConditionNode
83
66
return sub_mutex;
84
67
}
85
68
69
+ using SubscribersRegistry =
70
+ std::unordered_map<std::string, std::weak_ptr<SubscriberInstance>>;
71
+
86
72
// 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 ()
89
74
{
90
- static std::unordered_map<std::string, std::shared_ptr<SubscriberInstance>>
91
- subscribers_registry;
75
+ static SubscribersRegistry subscribers_registry;
92
76
return subscribers_registry;
93
77
}
94
78
@@ -108,7 +92,7 @@ class RosTopicSubNode : public BT::ConditionNode
108
92
/* * You are not supposed to instantiate this class directly, the factory will do it.
109
93
* To register this class into the factory, use:
110
94
*
111
- * RegisterRosAction<DerivedClasss >(factory, params)
95
+ * RegisterRosAction<DerivedClass >(factory, params)
112
96
*
113
97
* Note that if the external_action_client is not set, the constructor will build its own.
114
98
* */
@@ -118,22 +102,6 @@ class RosTopicSubNode : public BT::ConditionNode
118
102
virtual ~RosTopicSubNode ()
119
103
{
120
104
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
- }
137
105
}
138
106
139
107
/* *
@@ -190,6 +158,26 @@ class RosTopicSubNode : public BT::ConditionNode
190
158
// ----------------------------------------------------------------
191
159
// ---------------------- DEFINITIONS -----------------------------
192
160
// ----------------------------------------------------------------
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
+ }
193
181
194
182
template <class T >
195
183
inline RosTopicSubNode<T>::RosTopicSubNode(const std::string& instance_name,
@@ -262,17 +250,15 @@ inline bool RosTopicSubNode<T>::createSubscriber(const std::string& topic_name)
262
250
auto it = registry.find (subscriber_key_);
263
251
if (it == registry.end ())
264
252
{
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_ });
269
255
270
256
RCLCPP_INFO (logger (), " Node [%s] created Subscriber to topic [%s]" , name ().c_str (),
271
257
topic_name.c_str ());
272
258
}
273
259
else
274
260
{
275
- sub_instance_ = it->second ;
261
+ sub_instance_ = it->second . lock () ;
276
262
}
277
263
278
264
// Check if there was a message received before the creation of this subscriber action
0 commit comments