@@ -97,7 +97,18 @@ class RosActionNode : public BT::ActionNodeBase
9797 explicit RosActionNode (const std::string& instance_name, const BT::NodeConfig& conf,
9898 const RosNodeParams& params);
9999
100- virtual ~RosActionNode () = default ;
100+ virtual ~RosActionNode ()
101+ {
102+ std::unique_lock lk (getMutex ());
103+ auto & registry = getRegistry ();
104+ for (auto it = registry.begin (); it != registry.end (); ) {
105+ if (it->second .expired ()) {
106+ it = registry.erase (it);
107+ } else {
108+ ++it;
109+ }
110+ }
111+ }
101112
102113 /* *
103114 * @brief Any subclass of RosActionNode that has ports must implement a
@@ -229,7 +240,6 @@ class RosActionNode : public BT::ActionNodeBase
229240
230241 rclcpp::Time time_goal_sent_;
231242 NodeStatus on_feedback_state_change_;
232- bool goal_received_;
233243 WrappedResult result_;
234244
235245 bool createClient (const std::string& action_name);
@@ -302,22 +312,25 @@ inline bool RosActionNode<T>::createClient(const std::string& action_name)
302312 throw RuntimeError (" The ROS node went out of scope. RosNodeParams doesn't take the "
303313 " ownership of the node." );
304314 }
305- action_client_key_ = std::string (node->get_fully_qualified_name ()) + " /" + action_name;
306315
307- auto & registry = getRegistry ();
308- auto it = registry.find (action_client_key_);
309- if (it == registry.end () || it->second .expired ())
316+ const auto key = std::string (node->get_fully_qualified_name ()) + " /" + action_name;
317+ if (key != action_client_key_ || action_name_ != action_name || !client_instance_)
310318 {
311- client_instance_ = std::make_shared<ActionClientInstance>(node, action_name);
312- registry.insert ({ action_client_key_, client_instance_ });
313- }
314- else
315- {
316- client_instance_ = it->second .lock ();
319+ auto & registry = getRegistry ();
320+ auto it = registry.find (key);
321+ if (it == registry.end () || it->second .expired ())
322+ {
323+ client_instance_ = std::make_shared<ActionClientInstance>(node, action_name);
324+ registry[key] = client_instance_;
325+ }
326+ else
327+ {
328+ client_instance_ = it->second .lock ();
329+ }
330+ action_client_key_ = key;
331+ action_name_ = action_name;
317332 }
318333
319- action_name_ = action_name;
320-
321334 bool found =
322335 client_instance_->action_client ->wait_for_action_server (wait_for_server_timeout_);
323336 if (!found)
@@ -381,7 +394,7 @@ inline NodeStatus RosActionNode<T>::tick()
381394 {
382395 setStatus (NodeStatus::RUNNING);
383396
384- goal_received_ = false ;
397+ goal_handle_. reset () ;
385398 future_goal_handle_ = {};
386399 on_feedback_state_change_ = NodeStatus::RUNNING;
387400 result_ = {};
@@ -417,9 +430,8 @@ inline NodeStatus RosActionNode<T>::tick()
417430 };
418431 // --------------------
419432 goal_options.goal_response_callback =
420- [this ](typename GoalHandle::SharedPtr const future_handle) {
421- auto goal_handle_ = future_handle.get ();
422- if (!goal_handle_)
433+ [this ](typename GoalHandle::SharedPtr const goal_handle) {
434+ if (!goal_handle || !(*goal_handle))
423435 {
424436 RCLCPP_ERROR (logger (), " Goal was rejected by server" );
425437 }
@@ -447,7 +459,7 @@ inline NodeStatus RosActionNode<T>::tick()
447459 client_instance_->callback_executor .spin_some ();
448460
449461 // FIRST case: check if the goal request has a timeout
450- if (!goal_received_ )
462+ if (!goal_handle_ )
451463 {
452464 auto nodelay = std::chrono::milliseconds (0 );
453465 auto timeout =
@@ -468,7 +480,6 @@ inline NodeStatus RosActionNode<T>::tick()
468480 }
469481 else
470482 {
471- goal_received_ = true ;
472483 goal_handle_ = future_goal_handle_.get ();
473484 future_goal_handle_ = {};
474485
0 commit comments