15 #ifndef NAV2_ROS_COMMON__LIFECYCLE_NODE_HPP_
16 #define NAV2_ROS_COMMON__LIFECYCLE_NODE_HPP_
25 #include "lifecycle_msgs/msg/state.hpp"
26 #include "nav2_ros_common/node_utils.hpp"
27 #include "rcl_interfaces/msg/parameter_descriptor.hpp"
28 #include "nav2_ros_common/node_thread.hpp"
29 #include "rclcpp_lifecycle/lifecycle_node.hpp"
30 #include "rclcpp/callback_group.hpp"
31 #include "rclcpp/context.hpp"
32 #include "rclcpp/create_timer.hpp"
33 #include "rclcpp/logging.hpp"
34 #include "rclcpp/node_options.hpp"
35 #include "rclcpp/parameter.hpp"
36 #include "rclcpp/qos.hpp"
37 #include "rclcpp/timer.hpp"
38 #include "bondcpp/bond.hpp"
39 #include "bond/msg/constants.hpp"
40 #include "nav2_ros_common/interface_factories.hpp"
41 #include "nav2_ros_common/rate.hpp"
46 using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn;
47 using namespace std::chrono_literals;
56 using SharedPtr = std::shared_ptr<nav2::LifecycleNode>;
57 using WeakPtr = std::weak_ptr<nav2::LifecycleNode>;
58 using SharedConstPointer = std::shared_ptr<const nav2::LifecycleNode>;
67 const std::string & node_name,
68 const std::string & ns,
69 const rclcpp::NodeOptions & options = rclcpp::NodeOptions())
70 : rclcpp_lifecycle::
LifecycleNode(node_name, ns, options, getEnableLifecycleServices(options))
73 this->declare_parameter(bond::msg::Constants::DISABLE_HEARTBEAT_TIMEOUT_PARAM,
true);
76 bond::msg::Constants::DISABLE_HEARTBEAT_TIMEOUT_PARAM,
true));
78 bond_heartbeat_period = this->declare_or_get_parameter<double>(
"bond_heartbeat_period", 0.25);
79 bool autostart_node = this->declare_or_get_parameter(
"autostart_node",
false);
84 printLifecycleNodeNotification();
86 register_rcl_preshutdown_callback();
95 const std::string & node_name,
96 const rclcpp::NodeOptions & options = rclcpp::NodeOptions())
102 RCLCPP_INFO(get_logger(),
"Destroying");
106 if (rcl_preshutdown_cb_handle_) {
107 rclcpp::Context::SharedPtr context = get_node_base_interface()->get_context();
108 context->remove_pre_shutdown_callback(*(rcl_preshutdown_cb_handle_.get()));
109 rcl_preshutdown_cb_handle_.reset();
121 template<
typename ParameterT>
123 const std::string & parameter_name,
124 const ParameterDescriptor & parameter_descriptor = ParameterDescriptor())
126 return nav2::declare_or_get_parameter<ParameterT>(
127 this, parameter_name, parameter_descriptor);
139 template<
typename ParamType>
141 const std::string & parameter_name,
142 const ParamType & default_value,
143 const ParameterDescriptor & parameter_descriptor = ParameterDescriptor())
145 return nav2::declare_or_get_parameter(
146 this, parameter_name,
147 default_value, parameter_descriptor);
161 typename nav2::Subscription<MessageT>::SharedPtr
163 const std::string & topic_name,
164 CallbackT && callback,
166 const rclcpp::CallbackGroup::SharedPtr & callback_group =
nullptr)
168 return nav2::interfaces::create_subscription<MessageT>(
169 shared_from_this(), topic_name,
170 std::forward<CallbackT>(callback), qos, callback_group);
181 template<
typename MessageT>
182 typename nav2::Publisher<MessageT>::SharedPtr
184 const std::string & topic_name,
186 const rclcpp::CallbackGroup::SharedPtr & callback_group =
nullptr,
187 rclcpp::PublisherMatchedCallbackType matched_callback =
nullptr)
189 auto pub = nav2::interfaces::create_publisher<MessageT>(
190 shared_from_this(), topic_name, qos, callback_group, matched_callback);
191 this->add_managed_entity(pub);
194 if (get_current_state().
id() ==
195 lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE)
209 template<
typename ServiceT>
210 typename nav2::ServiceClient<ServiceT>::SharedPtr
212 const std::string & service_name,
213 bool use_internal_executor =
false)
215 return nav2::interfaces::create_client<ServiceT>(
216 shared_from_this(), service_name, use_internal_executor);
226 template<
typename ServiceT>
227 typename nav2::ServiceServer<ServiceT>::SharedPtr
229 const std::string & service_name,
230 typename nav2::ServiceServer<ServiceT>::CallbackType cb,
231 rclcpp::CallbackGroup::SharedPtr callback_group =
nullptr)
233 return nav2::interfaces::create_service<ServiceT>(
234 shared_from_this(), service_name, cb, callback_group);
244 template<
typename DurationRepT,
typename DurationT,
typename CallbackT>
245 typename rclcpp::GenericTimer<CallbackT>::SharedPtr
247 std::chrono::duration<DurationRepT, DurationT> period,
249 rclcpp::CallbackGroup::SharedPtr group =
nullptr)
251 return rclcpp::create_timer(
252 nav2::selectSteadyOrSimClock(
this),
256 this->get_node_base_interface().get(),
257 this->get_node_timers_interface().get());
270 template<
typename ActionT>
271 typename nav2::SimpleActionServer<ActionT>::SharedPtr
273 const std::string & action_name,
274 typename nav2::SimpleActionServer<ActionT>::ExecuteCallback execute_callback,
275 typename nav2::SimpleActionServer<ActionT>::GoalReceivedCallback goal_received_callback =
277 typename nav2::SimpleActionServer<ActionT>::CompletionCallback compl_cb =
nullptr,
278 std::chrono::milliseconds server_timeout = std::chrono::milliseconds(500),
279 bool spin_thread =
false,
280 const bool realtime =
false)
282 return nav2::interfaces::create_action_server<ActionT>(
283 shared_from_this(), action_name, execute_callback,
284 goal_received_callback, compl_cb, server_timeout, spin_thread, realtime);
293 template<
typename ActionT>
294 typename nav2::ActionClient<ActionT>::SharedPtr
296 const std::string & action_name,
297 rclcpp::CallbackGroup::SharedPtr callback_group =
nullptr)
299 return nav2::interfaces::create_action_client<ActionT>(
300 shared_from_this(), action_name, callback_group);
308 return std::static_pointer_cast<nav2::LifecycleNode>(
309 rclcpp_lifecycle::LifecycleNode::shared_from_this());
317 return std::static_pointer_cast<nav2::LifecycleNode>(
318 rclcpp_lifecycle::LifecycleNode::shared_from_this());
327 nav2::CallbackReturn
on_error(
const rclcpp_lifecycle::State & )
331 "Lifecycle node %s does not have error state implemented", get_name());
332 return nav2::CallbackReturn::SUCCESS;
340 using lifecycle_msgs::msg::State;
341 autostart_timer_ = this->create_timer(
344 autostart_timer_->cancel();
345 RCLCPP_INFO(get_logger(),
"Auto-starting node: %s", this->get_name());
346 if (configure().
id() != State::PRIMARY_STATE_INACTIVE) {
348 get_logger(),
"Auto-starting node %s failed to configure!", this->get_name());
351 if (activate().
id() != State::PRIMARY_STATE_ACTIVE) {
353 get_logger(),
"Auto-starting node %s failed to activate!", this->get_name());
366 get_logger(),
"Running Nav2 LifecycleNode rcl preshutdown (%s)",
379 if (bond_heartbeat_period > 0.0) {
380 RCLCPP_INFO(get_logger(),
"Creating bond (%s) to lifecycle manager.", this->get_name());
382 bond_ = std::make_shared<bond::Bond>(
387 bond_->setHeartbeatPeriod(bond_heartbeat_period);
388 bond_->setHeartbeatTimeout(4.0);
398 if (bond_heartbeat_period > 0.0) {
399 RCLCPP_INFO(get_logger(),
"Destroying bond (%s) to lifecycle manager.", this->get_name());
415 "\n\t%s lifecycle node launched. \n"
416 "\tWaiting on external lifecycle transitions to activate\n"
417 "\tSee https://design.ros2.org/articles/node_lifecycle.html for more information.",
428 rclcpp::Context::SharedPtr context = get_node_base_interface()->get_context();
430 rcl_preshutdown_cb_handle_ = std::make_unique<rclcpp::PreShutdownCallbackHandle>(
431 context->add_pre_shutdown_callback(
446 if (get_current_state().
id() ==
447 lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE)
452 if (get_current_state().
id() ==
453 lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
460 std::unique_ptr<rclcpp::PreShutdownCallbackHandle> rcl_preshutdown_cb_handle_{
nullptr};
461 std::shared_ptr<bond::Bond> bond_{
nullptr};
462 double bond_heartbeat_period{0.1};
463 rclcpp::TimerBase::SharedPtr autostart_timer_;
471 static bool getEnableLifecycleServices(
const rclcpp::NodeOptions & options)
474 for (
const auto & param : options.parameter_overrides()) {
475 if (param.get_name() ==
"enable_lifecycle_services") {
476 return param.as_bool();
A lifecycle node wrapper to enable common Nav2 needs such as manipulating parameters.
nav2::CallbackReturn on_error(const rclcpp_lifecycle::State &)
Abstracted on_error state transition callback, since unimplemented as of 2020 in the managed ROS2 nod...
void autostart()
Automatically configure and active the node.
void destroyBond()
Destroy bond connection to lifecycle manager.
nav2::LifecycleNode::SharedPtr shared_from_this()
Get a shared pointer of this.
void printLifecycleNodeNotification()
Print notifications for lifecycle node.
nav2::Publisher< MessageT >::SharedPtr create_publisher(const std::string &topic_name, const rclcpp::QoS &qos=nav2::qos::StandardTopicQoS(), const rclcpp::CallbackGroup::SharedPtr &callback_group=nullptr, rclcpp::PublisherMatchedCallbackType matched_callback=nullptr)
Create a publisher to a topic using Nav2 QoS profiles and PublisherOptions.
rclcpp::GenericTimer< CallbackT >::SharedPtr create_timer(std::chrono::duration< DurationRepT, DurationT > period, CallbackT callback, rclcpp::CallbackGroup::SharedPtr group=nullptr)
Create a sim-time-aware timer for Nav2 lifecycle nodes.
ParameterT declare_or_get_parameter(const std::string ¶meter_name, const ParameterDescriptor ¶meter_descriptor=ParameterDescriptor())
Declares or gets a parameter with specified type (not value). If the parameter is already declared,...
nav2::SimpleActionServer< ActionT >::SharedPtr create_action_server(const std::string &action_name, typename nav2::SimpleActionServer< ActionT >::ExecuteCallback execute_callback, typename nav2::SimpleActionServer< ActionT >::GoalReceivedCallback goal_received_callback=nullptr, typename nav2::SimpleActionServer< ActionT >::CompletionCallback compl_cb=nullptr, std::chrono::milliseconds server_timeout=std::chrono::milliseconds(500), bool spin_thread=false, const bool realtime=false)
Create a SimpleActionServer to host with an action.
nav2::ServiceClient< ServiceT >::SharedPtr create_client(const std::string &service_name, bool use_internal_executor=false)
Create a ServiceClient to interface with a service.
void createBond()
Create bond connection to lifecycle manager.
LifecycleNode(const std::string &node_name, const std::string &ns, const rclcpp::NodeOptions &options=rclcpp::NodeOptions())
A lifecycle node constructor.
virtual void on_rcl_preshutdown()
Perform preshutdown activities before our Context is shutdown. Note that this is related to our Conte...
nav2::Subscription< MessageT >::SharedPtr create_subscription(const std::string &topic_name, CallbackT &&callback, const rclcpp::QoS &qos=nav2::qos::StandardTopicQoS(), const rclcpp::CallbackGroup::SharedPtr &callback_group=nullptr)
Create a subscription to a topic using Nav2 QoS profiles and SubscriptionOptions.
nav2::ServiceServer< ServiceT >::SharedPtr create_service(const std::string &service_name, typename nav2::ServiceServer< ServiceT >::CallbackType cb, rclcpp::CallbackGroup::SharedPtr callback_group=nullptr)
Create a ServiceServer to host with a service.
nav2::LifecycleNode::WeakPtr weak_from_this()
Get a shared pointer of this.
void register_rcl_preshutdown_callback()
ParamType declare_or_get_parameter(const std::string ¶meter_name, const ParamType &default_value, const ParameterDescriptor ¶meter_descriptor=ParameterDescriptor())
Declares or gets a parameter. If the parameter is already declared, returns its value; otherwise decl...
nav2::ActionClient< ActionT >::SharedPtr create_action_client(const std::string &action_name, rclcpp::CallbackGroup::SharedPtr callback_group=nullptr)
Create a ActionClient to call an action using.
LifecycleNode(const std::string &node_name, const rclcpp::NodeOptions &options=rclcpp::NodeOptions())
A lifecycle node constructor with no namespace.
A QoS profile for standard reliable topics with a history of 10 messages.