scenario_simulator_v2 C++ API
openscenario_interpreter.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 OPENSCENARIO_INTERPRETER__OPENSCENARIO_INTERPRETER_HPP_
16 #define OPENSCENARIO_INTERPRETER__OPENSCENARIO_INTERPRETER_HPP_
17 
18 #include <boost/variant.hpp>
19 #include <chrono>
20 #include <lifecycle_msgs/msg/state.hpp>
21 #include <lifecycle_msgs/msg/transition.hpp>
22 #include <memory>
30 #include <openscenario_interpreter_msgs/msg/context.hpp>
31 #include <rclcpp/rclcpp.hpp>
32 #include <rclcpp_lifecycle/lifecycle_node.hpp>
34 #include <simple_junit/junit5.hpp>
35 #include <utility>
36 
37 #define INTERPRETER_INFO_STREAM(...) \
38  RCLCPP_INFO_STREAM(get_logger(), "\x1b[32m" << __VA_ARGS__ << "\x1b[0m")
39 
40 // NOTE: Error on simulation is not error of the interpreter; so we print error messages into
41 // INFO_STREAM.
42 #define INTERPRETER_ERROR_STREAM(...) \
43  RCLCPP_INFO_STREAM(get_logger(), "\x1b[1;31m" << __VA_ARGS__ << "\x1b[0m")
44 
46 {
47 class Interpreter : public rclcpp_lifecycle::LifecycleNode,
50 {
51  using Context = openscenario_interpreter_msgs::msg::Context;
52 
53  const rclcpp_lifecycle::LifecyclePublisher<Context>::SharedPtr publisher_of_context;
54 
55  double local_frame_rate;
56 
57  double local_real_time_factor;
58 
59  String osc_path;
60 
61  String output_directory;
62 
63  bool publish_empty_context;
64 
65  bool record;
66 
67  std::shared_ptr<OpenScenario> script;
68 
69  std::list<std::shared_ptr<ScenarioDefinition>> scenarios;
70 
71  std::shared_ptr<rclcpp::TimerBase> timer;
72 
73  common::JUnit5 results;
74 
75  boost::variant<common::junit::Pass, common::junit::Failure, common::junit::Error> result;
76 
77  ExecutionTimer<> execution_timer;
78 
79  using Result = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn;
80 
81  bool waiting_for_engagement_to_be_completed = false; // NOTE: DIRTY HACK!!!
82 
83 public:
85  explicit Interpreter(const rclcpp::NodeOptions &);
86 
87  ~Interpreter() override;
88 
89  auto currentLocalFrameRate() const -> std::chrono::milliseconds;
90 
91  auto currentScenarioDefinition() const -> const std::shared_ptr<ScenarioDefinition> &;
92 
93  auto engage() const -> void;
94 
95  auto engageable() const -> bool;
96 
97  auto engaged() const -> bool;
98 
100 
101  auto on_activate(const rclcpp_lifecycle::State &) -> Result override;
102 
103  auto on_cleanup(const rclcpp_lifecycle::State &) -> Result override;
104 
105  auto on_configure(const rclcpp_lifecycle::State &) -> Result override;
106 
107  auto on_deactivate(const rclcpp_lifecycle::State &) -> Result override;
108 
109  auto on_error(const rclcpp_lifecycle::State &) -> Result override;
110 
111  auto on_shutdown(const rclcpp_lifecycle::State &) -> Result override;
112 
113  auto publishCurrentContext() const -> void;
114 
115  auto reset() -> void;
116 
117  template <typename T, typename... Ts>
118  auto set(Ts &&... xs) -> void
119  {
120  result = T(std::forward<decltype(xs)>(xs)...);
121 
122  results.name = boost::filesystem::path(osc_path).parent_path().parent_path().string();
123 
124  const auto suite_name = boost::filesystem::path(osc_path).parent_path().filename().string();
125 
126  const auto case_name = boost::filesystem::path(osc_path).stem().string();
127 
128  boost::apply_visitor(
129  overload(
130  [&](const common::junit::Pass & it) {
131  results.testsuite(suite_name).testcase(case_name).pass.push_back(it);
132  },
133  [&](const common::junit::Failure & it) {
134  results.testsuite(suite_name).testcase(case_name).failure.push_back(it);
135  },
136  [&](const common::junit::Error & it) {
137  results.testsuite(suite_name).testcase(case_name).error.push_back(it);
138  }),
139  result);
140 
141  results.write_to(
142  (boost::filesystem::path(output_directory) / "result.junit.xml").c_str(), " ");
143  }
144 
145  template <typename ExceptionHandler, typename Thunk>
146  auto withExceptionHandler(ExceptionHandler && handle, Thunk && thunk) -> decltype(auto)
147  {
148  try {
149  return thunk();
150  }
151 
152  catch (const SpecialAction<EXIT_SUCCESS> & action) // from CustomCommandAction::exitSuccess
153  {
154  set<common::junit::Pass>();
155  return handle(action);
156  }
157 
158  catch (const SpecialAction<EXIT_FAILURE> & action) // from CustomCommandAction::exitFailure
159  {
160  set<common::junit::Failure>("SimulationFailure", action.what());
161  return handle(action);
162  }
163 
164  catch (const AutowareError & error) {
165  set<common::junit::Error>("AutowareError", error.what());
166  return handle(error);
167  }
168 
169  catch (const SemanticError & error) {
170  set<common::junit::Error>("SemanticError", error.what());
171  return handle(error);
172  }
173 
174  catch (const SimulationError & error) {
175  set<common::junit::Error>("SimulationError", error.what());
176  return handle(error);
177  }
178 
179  catch (const SyntaxError & error) {
180  set<common::junit::Error>("SyntaxError", error.what());
181  return handle(error);
182  }
183 
184  catch (const std::exception & error) // NOTE: MUST BE LAST OF CATCH STATEMENTS.
185  {
186  set<common::junit::Error>("InternalError", error.what());
187  return handle(error);
188  }
189 
190  catch (...) // FINAL BARRIER
191  {
192  set<common::junit::Error>("UnknownError", "An unknown exception has occurred");
193  return handle();
194  }
195  }
196 
197  template <typename TimeoutHandler, typename Thunk>
198  auto withTimeoutHandler(TimeoutHandler && handle, Thunk && thunk) -> decltype(auto)
199  {
200  if (const auto time = execution_timer.invoke("", thunk); currentLocalFrameRate() < time) {
201  handle(execution_timer.getStatistics(""));
202  }
203  }
204 
206  {
207  /*
208  Ideally, the scenario should be terminated with an error if the total
209  time for the ScenarioDefinition evaluation and the traffic_simulator's
210  updateFrame exceeds the time allowed for a single frame. However, we
211  have found that many users are in environments where it is not possible
212  to run the simulator stably at 30 FPS (the default setting) while
213  running Autoware. In order to prioritize comfortable daily use, we
214  decided to give up full reproducibility of the scenario and only provide
215  warnings.
216  */
217 
218  return [this](const auto & statistics) {
219  RCLCPP_WARN_STREAM(
220  get_logger(),
221  "Your machine is not powerful enough to run the scenario at the specified frame rate ("
222  << local_frame_rate << " Hz). We recommend that you reduce the frame rate to "
223  << 1000.0 / statistics.template max<std::chrono::milliseconds>().count() << " or less.");
224  };
225  }
226 };
227 } // namespace openscenario_interpreter
228 
229 #endif // OPENSCENARIO_INTERPRETER__OPENSCENARIO_INTERPRETER_HPP_
Definition: openscenario_interpreter.hpp:50
auto engage() const -> void
Definition: openscenario_interpreter.cpp:142
auto on_error(const rclcpp_lifecycle::State &) -> Result override
Definition: openscenario_interpreter.cpp:274
auto currentLocalFrameRate() const -> std::chrono::milliseconds
Definition: openscenario_interpreter.cpp:61
auto on_cleanup(const rclcpp_lifecycle::State &) -> Result override
Definition: openscenario_interpreter.cpp:267
auto defaultTimeoutHandler() const
Definition: openscenario_interpreter.hpp:205
auto engageable() const -> bool
Definition: openscenario_interpreter.cpp:154
auto on_shutdown(const rclcpp_lifecycle::State &) -> Result override
Definition: openscenario_interpreter.cpp:281
auto makeCurrentConfiguration() const -> traffic_simulator::Configuration
Definition: openscenario_interpreter.cpp:71
auto engaged() const -> bool
Definition: openscenario_interpreter.cpp:167
auto publishCurrentContext() const -> void
Definition: openscenario_interpreter.cpp:290
auto withTimeoutHandler(TimeoutHandler &&handle, Thunk &&thunk) -> decltype(auto)
Definition: openscenario_interpreter.hpp:198
auto withExceptionHandler(ExceptionHandler &&handle, Thunk &&thunk) -> decltype(auto)
Definition: openscenario_interpreter.hpp:146
auto on_activate(const rclcpp_lifecycle::State &) -> Result override
Definition: openscenario_interpreter.cpp:180
OPENSCENARIO_INTERPRETER_PUBLIC Interpreter(const rclcpp::NodeOptions &)
Definition: openscenario_interpreter.cpp:37
auto on_deactivate(const rclcpp_lifecycle::State &) -> Result override
Definition: openscenario_interpreter.cpp:260
auto set(Ts &&... xs) -> void
Definition: openscenario_interpreter.hpp:118
auto currentScenarioDefinition() const -> const std::shared_ptr< ScenarioDefinition > &
Definition: openscenario_interpreter.cpp:66
~Interpreter() override
Definition: openscenario_interpreter.cpp:59
auto on_configure(const rclcpp_lifecycle::State &) -> Result override
Definition: openscenario_interpreter.cpp:89
auto reset() -> void
Definition: openscenario_interpreter.cpp:308
Definition: custom_command_action.hpp:38
Definition: execution_timer.hpp:29
auto invoke(const std::string &tag, Thunk &&thunk)
Definition: execution_timer.hpp:98
auto getStatistics(const std::string &tag) -> const auto &
Definition: execution_timer.hpp:113
std::string String
Definition: string.hpp:24
constexpr auto overload(Ts &&... xs) -> typename utility::overloaded< typename std::decay< Ts >::type... >
Definition: overload.hpp:51
Definition: hypot.hpp:22
Definition: junit5.hpp:25
#define OPENSCENARIO_INTERPRETER_PUBLIC
Definition: visibility.hpp:49
Definition: junit5.hpp:88
Definition: junit5.hpp:51
Definition: junit5.hpp:34
Definition: junit5.hpp:336
xs::string name
Definition: junit5.hpp:337
auto write_to(Ts &&... xs) const
Definition: junit5.hpp:381
auto testsuite(const xs::string &name) -> auto &
Definition: junit5.hpp:341
Definition: custom_command_action.hpp:32
Definition: configuration.hpp:30