Nav2 Navigation Stack - jazzy  jazzy
ROS 2 Navigation Stack
lifecycle_node.cpp
1 // Copyright (c) 2019 Intel Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "nav2_util/lifecycle_node.hpp"
16 
17 #include <memory>
18 #include <string>
19 #include <vector>
20 
21 #include "lifecycle_msgs/msg/state.hpp"
22 #include "nav2_util/node_utils.hpp"
23 
24 using namespace std::chrono_literals;
25 
26 namespace nav2_util
27 {
28 
29 LifecycleNode::LifecycleNode(
30  const std::string & node_name,
31  const std::string & ns,
32  const rclcpp::NodeOptions & options)
33 : rclcpp_lifecycle::LifecycleNode(node_name, ns, options)
34 {
35  // server side never times out from lifecycle manager
36  this->declare_parameter(bond::msg::Constants::DISABLE_HEARTBEAT_TIMEOUT_PARAM, true);
37  this->set_parameter(
38  rclcpp::Parameter(
39  bond::msg::Constants::DISABLE_HEARTBEAT_TIMEOUT_PARAM, true));
40 
41  nav2_util::declare_parameter_if_not_declared(
42  this, "bond_heartbeat_period", rclcpp::ParameterValue(0.1));
43  this->get_parameter("bond_heartbeat_period", bond_heartbeat_period);
44 
45  bool autostart_node = false;
46  nav2_util::declare_parameter_if_not_declared(
47  this, "autostart_node", rclcpp::ParameterValue(false));
48  this->get_parameter("autostart_node", autostart_node);
49  if (autostart_node) {
50  autostart();
51  }
52 
54 
56 }
57 
58 LifecycleNode::~LifecycleNode()
59 {
60  RCLCPP_INFO(get_logger(), "Destroying");
61 
62  runCleanups();
63 
64  if (rcl_preshutdown_cb_handle_) {
65  rclcpp::Context::SharedPtr context = get_node_base_interface()->get_context();
66  context->remove_pre_shutdown_callback(*(rcl_preshutdown_cb_handle_.get()));
67  rcl_preshutdown_cb_handle_.reset();
68  }
69 }
70 
72 {
73  if (bond_heartbeat_period > 0.0) {
74  RCLCPP_INFO(get_logger(), "Creating bond (%s) to lifecycle manager.", this->get_name());
75 
76  bond_ = std::make_unique<bond::Bond>(
77  std::string("bond"),
78  this->get_name(),
80 
81  bond_->setHeartbeatPeriod(bond_heartbeat_period);
82  bond_->setHeartbeatTimeout(4.0);
83  bond_->start();
84  }
85 }
86 
88 {
89  using lifecycle_msgs::msg::State;
90  autostart_timer_ = this->create_wall_timer(
91  0s,
92  [this]() -> void {
93  autostart_timer_->cancel();
94  RCLCPP_INFO(get_logger(), "Auto-starting node: %s", this->get_name());
95  if (configure().id() != State::PRIMARY_STATE_INACTIVE) {
96  RCLCPP_ERROR(get_logger(), "Auto-starting node %s failed to configure!", this->get_name());
97  return;
98  }
99  if (activate().id() != State::PRIMARY_STATE_ACTIVE) {
100  RCLCPP_ERROR(get_logger(), "Auto-starting node %s failed to activate!", this->get_name());
101  }
102  });
103 }
104 
106 {
107  /*
108  * In case this lifecycle node wasn't properly shut down, do it here.
109  * We will give the user some ability to clean up properly here, but it's
110  * best effort; i.e. we aren't trying to account for all possible states.
111  */
112  if (get_current_state().id() ==
113  lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE)
114  {
115  this->deactivate();
116  }
117 
118  if (get_current_state().id() ==
119  lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
120  {
121  this->cleanup();
122  }
123 }
124 
126 {
127  RCLCPP_INFO(
128  get_logger(), "Running Nav2 LifecycleNode rcl preshutdown (%s)",
129  this->get_name());
130 
131  runCleanups();
132 
133  destroyBond();
134 }
135 
137 {
138  rclcpp::Context::SharedPtr context = get_node_base_interface()->get_context();
139 
140  rcl_preshutdown_cb_handle_ = std::make_unique<rclcpp::PreShutdownCallbackHandle>(
141  context->add_pre_shutdown_callback(
142  std::bind(&LifecycleNode::on_rcl_preshutdown, this))
143  );
144 }
145 
147 {
148  if (bond_heartbeat_period > 0.0) {
149  RCLCPP_INFO(get_logger(), "Destroying bond (%s) to lifecycle manager.", this->get_name());
150 
151  if (bond_) {
152  bond_.reset();
153  }
154  }
155 }
156 
158 {
159  RCLCPP_INFO(
160  get_logger(),
161  "\n\t%s lifecycle node launched. \n"
162  "\tWaiting on external lifecycle transitions to activate\n"
163  "\tSee https://design.ros2.org/articles/node_lifecycle.html for more information.", get_name());
164 }
165 
166 } // namespace nav2_util
A lifecycle node wrapper to enable common Nav2 needs such as manipulating parameters.
void autostart()
Automatically configure and active the node.
void printLifecycleNodeNotification()
Print notifications for lifecycle node.
std::shared_ptr< nav2_util::LifecycleNode > shared_from_this()
Get a shared pointer of this.
virtual void on_rcl_preshutdown()
Perform preshutdown activities before our Context is shutdown. Note that this is related to our Conte...
void createBond()
Create bond connection to lifecycle manager.
void destroyBond()
Destroy bond connection to lifecycle manager.