scenario_simulator_v2 C++ API
service_with_validation.hpp
Go to the documentation of this file.
1 // Copyright 2015 TIER IV, Inc. All rights reserved.
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 #ifndef CONCEALER__SERVICE_WITH_VALIDATION_HPP_
16 #define CONCEALER__SERVICE_WITH_VALIDATION_HPP_
17 
18 #include <autoware_adapi_v1_msgs/msg/response_status.hpp>
19 #include <chrono>
21 #include <rclcpp/rclcpp.hpp>
23 #include <string>
24 #include <tier4_external_api_msgs/msg/response_status.hpp>
25 #include <tier4_rtc_msgs/srv/auto_mode_with_module.hpp>
26 #include <type_traits>
27 
28 namespace concealer
29 {
30 template <typename T>
32 {
33  const std::string service_name;
34 
35  rclcpp::Logger logger;
36 
37  typename rclcpp::Client<T>::SharedPtr client;
38 
39  rclcpp::WallRate validation_rate;
40 
41 public:
42  template <typename FieldOperatorApplication>
44  const std::string & service_name, FieldOperatorApplication & autoware,
45  const std::chrono::nanoseconds validation_interval = std::chrono::seconds(1))
46  : service_name(service_name),
47  logger(autoware.get_logger()),
48  client(autoware.template create_client<T>(service_name, rmw_qos_profile_default)),
49  validation_rate(validation_interval)
50  {
51  }
52 
53  auto operator()(const typename T::Request::SharedPtr & request, std::size_t attempts_count)
54  -> void
55  {
56  while (!client->service_is_ready()) {
57  RCLCPP_INFO_STREAM(logger, service_name << " service is not ready.");
58  validation_rate.sleep();
59  }
60 
61  auto send = [this](const auto & request) {
62  if (auto future = client->async_send_request(request);
63  future.wait_for(validation_rate.period()) == std::future_status::ready) {
64  return std::optional<typename rclcpp::Client<T>::SharedFuture>(future);
65  } else {
66  RCLCPP_ERROR_STREAM(logger, service_name << " service request has timed out.");
67  return std::optional<typename rclcpp::Client<T>::SharedFuture>();
68  }
69  };
70 
71  for (std::size_t attempt = 0; attempt < attempts_count; ++attempt, validation_rate.sleep()) {
72  if (const auto & service_call_result = send(request)) {
73  if constexpr (DetectMember_status<typename T::Response>::value) {
74  if constexpr (std::is_same_v<
75  tier4_external_api_msgs::msg::ResponseStatus,
76  decltype(T::Response::status)>) {
77  if (const auto & service_call_status = service_call_result->get()->status;
78  service_call_status.code == tier4_external_api_msgs::msg::ResponseStatus::SUCCESS) {
79  RCLCPP_INFO_STREAM(
80  logger, service_name << " service request has been accepted"
81  << (service_call_status.message.empty()
82  ? "."
83  : " (" + service_call_status.message + ")."));
84  return;
85  } else {
86  RCLCPP_ERROR_STREAM(
87  logger, service_name
88  << " service request was accepted, but ResponseStatus is FAILURE"
89  << (service_call_status.message.empty()
90  ? "."
91  : " (" + service_call_status.message + ")"));
92  }
93  } else if constexpr (std::is_same_v<
94  autoware_adapi_v1_msgs::msg::ResponseStatus,
95  decltype(T::Response::status)>) {
96  if (const auto & service_call_status = service_call_result->get()->status;
97  service_call_status.success) {
98  RCLCPP_INFO_STREAM(
99  logger, service_name << " service request has been accepted"
100  << (service_call_status.message.empty()
101  ? "."
102  : " (" + service_call_status.message + ")."));
103  return;
104  } else {
105  RCLCPP_ERROR_STREAM(
106  logger, service_name << " service request was accepted, but "
107  "ResponseStatus::success is false with error code: "
108  << service_call_status.code << ", and message: "
109  << (service_call_status.message.empty()
110  ? ""
111  : " (" + service_call_status.message + ")"));
112  }
113  } else {
114  RCLCPP_INFO_STREAM(logger, service_name << " service request has been accepted.");
115  return;
116  }
117  } else if constexpr (DetectMember_success<typename T::Response>::value) {
118  if constexpr (std::is_same_v<bool, decltype(T::Response::success)>) {
119  if (service_call_result->get()->success) {
120  RCLCPP_INFO_STREAM(logger, service_name << " service request has been accepted.");
121  return;
122  } else {
123  RCLCPP_ERROR_STREAM(
124  logger, service_name
125  << " service request has been accepted, but Response::success is false.");
126  }
127  } else {
128  RCLCPP_INFO_STREAM(logger, service_name << " service request has been accepted.");
129  return;
130  }
131  } else {
132  RCLCPP_INFO_STREAM(logger, service_name << " service request has been accepted.");
133  return;
134  }
135  }
136  }
137 
139  "Requested the service ", std::quoted(service_name), " ", attempts_count,
140  " times, but was not successful.");
141  }
142 };
143 } // namespace concealer
144 
145 #endif //CONCEALER__SERVICE_WITH_VALIDATION_HPP_
Definition: service_with_validation.hpp:32
auto operator()(const typename T::Request::SharedPtr &request, std::size_t attempts_count) -> void
Definition: service_with_validation.hpp:53
ServiceWithValidation(const std::string &service_name, FieldOperatorApplication &autoware, const std::chrono::nanoseconds validation_interval=std::chrono::seconds(1))
Definition: service_with_validation.hpp:43
Definition: autoware_universe.hpp:40
constexpr int SUCCESS
Definition: constants.hpp:22
std::string string
Definition: junit5.hpp:26
Autoware encountered some problem that led to a simulation failure.
Definition: exception.hpp:41
Definition: field_operator_application.hpp:73