Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
lifecycle_bringup_commandline.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 <vector>
16 #include <string>
17 #include <iostream>
18 #include <cstdlib>
19 #include <chrono>
20 #include "rclcpp/node.hpp"
21 #include "rclcpp/utilities.hpp"
22 #include "nav2_util/lifecycle_service_client.hpp"
23 
24 using std::cerr;
25 using namespace std::chrono_literals; // NOLINT
26 using namespace nav2_util; // NOLINT
27 
28 void usage()
29 {
30  cerr << "Invalid command line.\n\n";
31  cerr << "This command will take a set of unconfigured lifecycle nodes through the\n";
32  cerr << "CONFIGURED to the ACTIVATED state\n";
33  cerr << "The nodes are brought up in the order listed on the command line\n\n";
34  cerr << "Usage:\n";
35  cerr << " > lifecycle_startup <node name> ...\n";
36  std::exit(1);
37 }
38 
39 #define RETRY(fn, retries) \
40  { \
41  int count = 0; \
42  while (true) { \
43  try { \
44  fn; \
45  break; \
46  } catch (const std::runtime_error & e) { \
47  ++count; \
48  if (count > (retries)) { \
49  throw e;} \
50  } \
51  } \
52  }
53 
54 inline void startupLifecycleNode(
55  rclcpp::Node::SharedPtr node, // nosemgrep
56  const std::string & node_name,
57  const std::chrono::seconds service_call_timeout,
58  const int retries)
59 {
60  LifecycleServiceClient sc(node_name, node);
61 
62  // Despite waiting for the service to be available and using reliable transport
63  // service calls still frequently hang. To get reliable startup it's necessary
64  // to timeout the service call and retry it when that happens.
65  RETRY(
66  sc.change_state(lifecycle_msgs::msg::Transition::TRANSITION_CONFIGURE, service_call_timeout),
67  retries);
68  RETRY(
69  sc.change_state(lifecycle_msgs::msg::Transition::TRANSITION_ACTIVATE, service_call_timeout),
70  retries);
71 }
72 
73 inline void startup_lifecycle_nodes(
74  rclcpp::Node::SharedPtr node, // nosemgrep
75  const std::vector<std::string> & node_names,
76  const std::chrono::seconds service_call_timeout,
77  const int retries = 3)
78 {
79  for (const auto & node_name : node_names) {
80  startupLifecycleNode(node, node_name, service_call_timeout, retries);
81  }
82 }
83 
84 
85 int main(int argc, char * argv[])
86 {
87  if (argc == 1) {
88  usage();
89  }
90  rclcpp::init(0, nullptr);
91  auto node = std::make_shared<rclcpp::Node>("lifecycle_bringup_client"); // nosemgrep
92  startup_lifecycle_nodes(
93  node,
94  std::vector<std::string>(argv + 1, argv + argc),
95  10s);
96  rclcpp::shutdown();
97 }
Helper functions to interact with a lifecycle node.