Nav2 Navigation Stack - kilted  kilted
ROS 2 Navigation Stack
lifecycle_service_client.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_service_client.hpp"
16 
17 #include <string>
18 #include <chrono>
19 #include <memory>
20 
21 #include "lifecycle_msgs/srv/change_state.hpp"
22 #include "lifecycle_msgs/srv/get_state.hpp"
23 
24 using nav2_util::generate_internal_node;
25 using std::chrono::milliseconds;
26 using std::make_shared;
27 using std::string;
28 using namespace std::chrono_literals;
29 
30 namespace nav2_util
31 {
32 
33 LifecycleServiceClient::LifecycleServiceClient(
34  const string & lifecycle_node_name)
35 : node_(generate_internal_node(lifecycle_node_name + "_lifecycle_client")),
36  change_state_(lifecycle_node_name + "/change_state", node_,
37  true /*creates and spins an internal executor*/),
38  get_state_(lifecycle_node_name + "/get_state", node_,
39  true /*creates and spins an internal executor*/)
40 {
41  // Block until server is up
42  rclcpp::Rate r(20);
43  while (!get_state_.wait_for_service(2s)) {
44  RCLCPP_INFO(
45  node_->get_logger(), "Waiting for service %s...", get_state_.getServiceName().c_str());
46  r.sleep();
47  }
48 }
49 
50 LifecycleServiceClient::LifecycleServiceClient(
51  const string & lifecycle_node_name,
52  rclcpp::Node::SharedPtr parent_node)
53 : node_(parent_node),
54  change_state_(lifecycle_node_name + "/change_state", node_,
55  true /*creates and spins an internal executor*/),
56  get_state_(lifecycle_node_name + "/get_state", node_,
57  true /*creates and spins an internal executor*/)
58 {
59  // Block until server is up
60  rclcpp::Rate r(20);
61  while (!get_state_.wait_for_service(2s)) {
62  RCLCPP_INFO(
63  node_->get_logger(), "Waiting for service %s...", get_state_.getServiceName().c_str());
64  r.sleep();
65  }
66 }
67 
68 bool LifecycleServiceClient::change_state(
69  const uint8_t transition,
70  const milliseconds transition_timeout,
71  const milliseconds wait_for_service_timeout)
72 {
73  if (!change_state_.wait_for_service(wait_for_service_timeout)) {
74  throw std::runtime_error("change_state service is not available!");
75  }
76 
77  auto request = std::make_shared<lifecycle_msgs::srv::ChangeState::Request>();
78  request->transition.id = transition;
79  if (transition_timeout > 0ms) {
80  auto response = change_state_.invoke(request, transition_timeout);
81  return response.get();
82  } else {
83  auto response = std::make_shared<lifecycle_msgs::srv::ChangeState::Response>();
84  return change_state_.invoke(request, response);
85  }
86 }
87 
88 uint8_t LifecycleServiceClient::get_state(
89  const milliseconds timeout)
90 {
91  if (!get_state_.wait_for_service(timeout)) {
92  throw std::runtime_error("get_state service is not available!");
93  }
94 
95  auto request = std::make_shared<lifecycle_msgs::srv::GetState::Request>();
96  auto result = get_state_.invoke(request, timeout);
97  return result->current_state.id;
98 }
99 
100 } // namespace nav2_util