3333namespace rclcpp
3434{
3535
36- class TimeSource :: ClocksState : public std::enable_shared_from_this<ClocksState>
36+ class ClocksState final
3737{
3838public:
3939 ClocksState ()
@@ -182,12 +182,11 @@ class TimeSource::ClocksState : public std::enable_shared_from_this<ClocksState>
182182 std::shared_ptr<const rosgraph_msgs::msg::Clock> last_msg_set_;
183183};
184184
185- class TimeSource ::NodeState : public std::enable_shared_from_this<NodeState>
185+ class TimeSource ::NodeState final
186186{
187187public:
188- NodeState (std::weak_ptr<ClocksState> clocks_state, const rclcpp::QoS & qos, bool use_clock_thread)
189- : clocks_state_(std::move(clocks_state)),
190- use_clock_thread_ (use_clock_thread),
188+ NodeState (const rclcpp::QoS & qos, bool use_clock_thread)
189+ : use_clock_thread_(use_clock_thread),
191190 logger_ (rclcpp::get_logger(" rclcpp" )),
192191 qos_(qos)
193192 {
@@ -250,94 +249,77 @@ class TimeSource::NodeState : public std::enable_shared_from_this<NodeState>
250249 if (!node_parameters_->has_parameter (use_sim_time_name)) {
251250 use_sim_time_param = node_parameters_->declare_parameter (
252251 use_sim_time_name,
253- rclcpp::ParameterValue (false ),
254- rcl_interfaces::msg::ParameterDescriptor ());
252+ rclcpp::ParameterValue (false ));
255253 } else {
256254 use_sim_time_param = node_parameters_->get_parameter (use_sim_time_name).get_parameter_value ();
257255 }
258256 if (use_sim_time_param.get_type () == rclcpp::PARAMETER_BOOL) {
259257 if (use_sim_time_param.get <bool >()) {
260258 parameter_state_ = SET_TRUE;
261- // There should be no way to call this attachNode when the clocks_state_ pointer is not
262- // valid because it means the TimeSource is being destroyed
263- if (auto clocks_state_ptr = clocks_state_.lock ()) {
264- clocks_state_ptr->enable_ros_time ();
265- create_clock_sub ();
266- }
259+ clocks_state_.enable_ros_time ();
260+ create_clock_sub ();
267261 }
268262 } else {
269263 RCLCPP_ERROR (
270264 logger_, " Invalid type '%s' for parameter 'use_sim_time', should be 'bool'" ,
271265 rclcpp::to_string (use_sim_time_param.get_type ()).c_str ());
266+ throw std::invalid_argument (" Invalid type for parameter 'use_sim_time', should be 'bool'" );
272267 }
273- sim_time_cb_handler_ = node_parameters_->add_on_set_parameters_callback (
274- [use_sim_time_name](const std::vector<rclcpp::Parameter> & parameters) {
275- rcl_interfaces::msg::SetParametersResult result;
276- result.successful = true ;
277- for (const auto & parameter : parameters) {
278- if (
279- parameter.get_name () == use_sim_time_name &&
280- parameter.get_type () != rclcpp::PARAMETER_BOOL)
281- {
282- result.successful = false ;
283- result.reason = " '" + use_sim_time_name + " ' must be a bool" ;
284- break ;
285- }
286- }
287- return result;
288- });
289268
290269 // TODO(tfoote) use parameters interface not subscribe to events via topic ticketed #609
291270 parameter_subscription_ = rclcpp::AsyncParametersClient::on_parameter_event (
292271 node_topics_,
293- [state = std::weak_ptr<NodeState>(this ->shared_from_this ())](
294- std::shared_ptr<const rcl_interfaces::msg::ParameterEvent> event) {
295- if (auto state_ptr = state.lock ()) {
296- state_ptr->on_parameter_event (event);
272+ [this ](std::shared_ptr<const rcl_interfaces::msg::ParameterEvent> event) {
273+ if (node_base_ != nullptr ) {
274+ this ->on_parameter_event (event);
297275 }
298- // Do nothing if the pointer could not be locked because it means the TimeSource is now
276+ // Do nothing if node_base_ is nullptr because it means the TimeSource is now
299277 // without an attached node
300278 });
301279 }
302280
303281 // Detach the attached node
304282 void detachNode ()
305283 {
306- // There should be no way to call detachNode when the clocks_state_ pointer is not valid
307- // because it means the TimeSource is being destroyed
308- if (auto clocks_state_ptr = clocks_state_.lock ()) {
309- clocks_state_ptr->disable_ros_time ();
310- }
284+ // destroy_clock_sub() *must* be first here, to ensure that the executor
285+ // can't possibly call any of the callbacks as we are cleaning up.
311286 destroy_clock_sub ();
287+ clocks_state_.disable_ros_time ();
312288 parameter_subscription_.reset ();
313289 node_base_.reset ();
314290 node_topics_.reset ();
315291 node_graph_.reset ();
316292 node_services_.reset ();
317293 node_logging_.reset ();
318294 node_clock_.reset ();
319- if (sim_time_cb_handler_ && node_parameters_) {
320- node_parameters_->remove_on_set_parameters_callback (sim_time_cb_handler_.get ());
321- }
322- sim_time_cb_handler_.reset ();
323295 node_parameters_.reset ();
324296 }
325297
298+ void attachClock (std::shared_ptr<rclcpp::Clock> clock)
299+ {
300+ clocks_state_.attachClock (std::move (clock));
301+ }
302+
303+ void detachClock (std::shared_ptr<rclcpp::Clock> clock)
304+ {
305+ clocks_state_.detachClock (std::move (clock));
306+ }
307+
326308private:
327- std::weak_ptr< ClocksState> clocks_state_;
309+ ClocksState clocks_state_;
328310
329311 // Dedicated thread for clock subscription.
330312 bool use_clock_thread_;
331313 std::thread clock_executor_thread_;
332314
333315 // Preserve the node reference
334- rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
335- rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_;
336- rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_;
337- rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_;
338- rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging_;
339- rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock_;
340- rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters_;
316+ rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_{ nullptr } ;
317+ rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_{ nullptr } ;
318+ rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_{ nullptr } ;
319+ rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_{ nullptr } ;
320+ rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging_{ nullptr } ;
321+ rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock_{ nullptr } ;
322+ rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters_{ nullptr } ;
341323
342324 // Store (and update on node attach) logger for logging.
343325 Logger logger_;
@@ -346,9 +328,7 @@ class TimeSource::NodeState : public std::enable_shared_from_this<NodeState>
346328 rclcpp::QoS qos_;
347329
348330 // The subscription for the clock callback
349- using MessageT = rosgraph_msgs::msg::Clock;
350- using Alloc = std::allocator<void >;
351- using SubscriptionT = rclcpp::Subscription<MessageT, Alloc>;
331+ using SubscriptionT = rclcpp::Subscription<rosgraph_msgs::msg::Clock>;
352332 std::shared_ptr<SubscriptionT> clock_subscription_{nullptr };
353333 std::mutex clock_sub_lock_;
354334 rclcpp::CallbackGroup::SharedPtr clock_callback_group_;
@@ -358,21 +338,15 @@ class TimeSource::NodeState : public std::enable_shared_from_this<NodeState>
358338 // The clock callback itself
359339 void clock_cb (std::shared_ptr<const rosgraph_msgs::msg::Clock> msg)
360340 {
361- auto clocks_state_ptr = clocks_state_.lock ();
362- if (!clocks_state_ptr) {
363- // The clock_state_ pointer is no longer valid, implying that the TimeSource object is being
364- // destroyed, so do nothing
365- return ;
366- }
367- if (!clocks_state_ptr->is_ros_time_active () && SET_TRUE == this ->parameter_state_ ) {
368- clocks_state_ptr->enable_ros_time ();
341+ if (!clocks_state_.is_ros_time_active () && SET_TRUE == this ->parameter_state_ ) {
342+ clocks_state_.enable_ros_time ();
369343 }
370344 // Cache the last message in case a new clock is attached.
371- clocks_state_ptr-> cache_last_msg (msg);
345+ clocks_state_. cache_last_msg (msg);
372346 auto time_msg = std::make_shared<builtin_interfaces::msg::Time>(msg->clock );
373347
374348 if (SET_TRUE == this ->parameter_state_ ) {
375- clocks_state_ptr-> set_all_clocks (time_msg, true );
349+ clocks_state_. set_all_clocks (time_msg, true );
376350 }
377351 }
378352
@@ -421,13 +395,12 @@ class TimeSource::NodeState : public std::enable_shared_from_this<NodeState>
421395 node_topics_,
422396 " /clock" ,
423397 qos_,
424- [state = std::weak_ptr<NodeState>(this ->shared_from_this ())](
425- std::shared_ptr<const rosgraph_msgs::msg::Clock> msg) {
426- if (auto state_ptr = state.lock ()) {
427- state_ptr->clock_cb (msg);
398+ [this ](std::shared_ptr<const rosgraph_msgs::msg::Clock> msg) {
399+ // We are using node_base_ as an indication if there is a node attached.
400+ // Only call the clock_cb if that is the case.
401+ if (node_base_ != nullptr ) {
402+ clock_cb (msg);
428403 }
429- // Do nothing if the pointer could not be locked because it means the TimeSource is now
430- // without an attached node
431404 },
432405 options
433406 );
@@ -447,19 +420,12 @@ class TimeSource::NodeState : public std::enable_shared_from_this<NodeState>
447420 }
448421
449422 // Parameter Event subscription
450- using ParamMessageT = rcl_interfaces::msg::ParameterEvent;
451- using ParamSubscriptionT = rclcpp::Subscription<ParamMessageT, Alloc>;
423+ using ParamSubscriptionT = rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>;
452424 std::shared_ptr<ParamSubscriptionT> parameter_subscription_;
453425
454426 // Callback for parameter updates
455427 void on_parameter_event (std::shared_ptr<const rcl_interfaces::msg::ParameterEvent> event)
456428 {
457- auto clocks_state_ptr = clocks_state_.lock ();
458- if (!clocks_state_ptr) {
459- // The clock_state_ pointer is no longer valid, implying that the TimeSource object is being
460- // destroyed, so do nothing
461- return ;
462- }
463429 // Filter out events on 'use_sim_time' parameter instances in other nodes.
464430 if (event->node != node_base_->get_fully_qualified_name ()) {
465431 return ;
@@ -475,41 +441,35 @@ class TimeSource::NodeState : public std::enable_shared_from_this<NodeState>
475441 }
476442 if (it.second ->value .bool_value ) {
477443 parameter_state_ = SET_TRUE;
478- clocks_state_ptr-> enable_ros_time ();
444+ clocks_state_. enable_ros_time ();
479445 create_clock_sub ();
480446 } else {
481447 parameter_state_ = SET_FALSE;
482- clocks_state_ptr->disable_ros_time ();
483448 destroy_clock_sub ();
449+ clocks_state_.disable_ros_time ();
484450 }
485451 }
486452 // Handle the case that use_sim_time was deleted.
487453 rclcpp::ParameterEventsFilter deleted (event, {" use_sim_time" },
488454 {rclcpp::ParameterEventsFilter::EventType::DELETED});
489455 for (auto & it : deleted.get_events ()) {
490456 (void ) it; // if there is a match it's already matched, don't bother reading it.
491- // If the parameter is deleted mark it as unset but dont' change state.
457+ // If the parameter is deleted mark it as unset but don't change state.
492458 parameter_state_ = UNSET;
493459 }
494460 }
495461
496462 // An enum to hold the parameter state
497463 enum UseSimTimeParameterState {UNSET, SET_TRUE, SET_FALSE};
498464 UseSimTimeParameterState parameter_state_;
499-
500- // A handler for the use_sim_time parameter callback.
501- rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr sim_time_cb_handler_{nullptr };
502465};
503466
504467TimeSource::TimeSource (
505468 std::shared_ptr<rclcpp::Node> node,
506469 const rclcpp::QoS & qos,
507470 bool use_clock_thread)
508- : constructed_use_clock_thread_(use_clock_thread),
509- constructed_qos_ (qos)
471+ : TimeSource(qos, use_clock_thread)
510472{
511- clocks_state_ = std::make_shared<ClocksState>();
512- node_state_ = std::make_shared<NodeState>(clocks_state_->weak_from_this (), qos, use_clock_thread);
513473 attachNode (node);
514474}
515475
@@ -519,8 +479,7 @@ TimeSource::TimeSource(
519479: constructed_use_clock_thread_(use_clock_thread),
520480 constructed_qos_ (qos)
521481{
522- clocks_state_ = std::make_shared<ClocksState>();
523- node_state_ = std::make_shared<NodeState>(clocks_state_->weak_from_this (), qos, use_clock_thread);
482+ node_state_ = std::make_shared<NodeState>(qos, use_clock_thread);
524483}
525484
526485void TimeSource::attachNode (rclcpp::Node::SharedPtr node)
@@ -559,19 +518,18 @@ void TimeSource::detachNode()
559518{
560519 node_state_.reset ();
561520 node_state_ = std::make_shared<NodeState>(
562- clocks_state_->weak_from_this (),
563521 constructed_qos_,
564522 constructed_use_clock_thread_);
565523}
566524
567525void TimeSource::attachClock (std::shared_ptr<rclcpp::Clock> clock)
568526{
569- clocks_state_ ->attachClock (std::move (clock));
527+ node_state_ ->attachClock (std::move (clock));
570528}
571529
572530void TimeSource::detachClock (std::shared_ptr<rclcpp::Clock> clock)
573531{
574- clocks_state_ ->detachClock (std::move (clock));
532+ node_state_ ->detachClock (std::move (clock));
575533}
576534
577535bool TimeSource::get_use_clock_thread ()
0 commit comments