@@ -97,7 +97,18 @@ class RosActionNode : public BT::ActionNodeBase
97
97
explicit RosActionNode (const std::string& instance_name, const BT::NodeConfig& conf,
98
98
const RosNodeParams& params);
99
99
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
+ }
101
112
102
113
/* *
103
114
* @brief Any subclass of RosActionNode that has ports must implement a
@@ -229,7 +240,6 @@ class RosActionNode : public BT::ActionNodeBase
229
240
230
241
rclcpp::Time time_goal_sent_;
231
242
NodeStatus on_feedback_state_change_;
232
- bool goal_received_;
233
243
WrappedResult result_;
234
244
235
245
bool createClient (const std::string& action_name);
@@ -302,22 +312,25 @@ inline bool RosActionNode<T>::createClient(const std::string& action_name)
302
312
throw RuntimeError (" The ROS node went out of scope. RosNodeParams doesn't take the "
303
313
" ownership of the node." );
304
314
}
305
- action_client_key_ = std::string (node->get_fully_qualified_name ()) + " /" + action_name;
306
315
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_)
310
318
{
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;
317
332
}
318
333
319
- action_name_ = action_name;
320
-
321
334
bool found =
322
335
client_instance_->action_client ->wait_for_action_server (wait_for_server_timeout_);
323
336
if (!found)
@@ -381,7 +394,7 @@ inline NodeStatus RosActionNode<T>::tick()
381
394
{
382
395
setStatus (NodeStatus::RUNNING);
383
396
384
- goal_received_ = false ;
397
+ goal_handle_. reset () ;
385
398
future_goal_handle_ = {};
386
399
on_feedback_state_change_ = NodeStatus::RUNNING;
387
400
result_ = {};
@@ -417,9 +430,8 @@ inline NodeStatus RosActionNode<T>::tick()
417
430
};
418
431
// --------------------
419
432
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))
423
435
{
424
436
RCLCPP_ERROR (logger (), " Goal was rejected by server" );
425
437
}
@@ -447,7 +459,7 @@ inline NodeStatus RosActionNode<T>::tick()
447
459
client_instance_->callback_executor .spin_some ();
448
460
449
461
// FIRST case: check if the goal request has a timeout
450
- if (!goal_received_ )
462
+ if (!goal_handle_ )
451
463
{
452
464
auto nodelay = std::chrono::milliseconds (0 );
453
465
auto timeout =
@@ -468,7 +480,6 @@ inline NodeStatus RosActionNode<T>::tick()
468
480
}
469
481
else
470
482
{
471
- goal_received_ = true ;
472
483
goal_handle_ = future_goal_handle_.get ();
473
484
future_goal_handle_ = {};
474
485
0 commit comments