scenario_simulator_v2 C++ API
api.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 TRAFFIC_SIMULATOR__API__API_HPP_
16 #define TRAFFIC_SIMULATOR__API__API_HPP_
17 
18 #include <simulation_api_schema.pb.h>
19 
20 #include <boost/variant.hpp>
21 #include <cassert>
22 #include <memory>
23 #include <optional>
24 #include <rclcpp/rclcpp.hpp>
25 #include <rosgraph_msgs/msg/clock.hpp>
28 #include <std_msgs/msg/float64.hpp>
29 #include <stdexcept>
30 #include <string>
44 #include <traffic_simulator_msgs/msg/behavior_parameter.hpp>
45 #include <utility>
46 
48 {
50 {
51  static auto autoware() noexcept -> const std::string &
52  {
53  static const std::string name = "Autoware";
54  return name;
55  }
56 };
57 
59 {
60 };
61 
62 class API
63 {
64 public:
65  template <typename NodeT, typename AllocatorT = std::allocator<void>, typename... Ts>
66  explicit API(NodeT && node, const Configuration & configuration, Ts &&... xs)
67  : configuration(configuration),
68  node_parameters_(
69  rclcpp::node_interfaces::get_node_parameters_interface(std::forward<NodeT>(node))),
70  entity_manager_ptr_(
71  std::make_shared<entity::EntityManager>(node, configuration, node_parameters_)),
72  traffic_lights_ptr_(std::make_shared<TrafficLights>(
73  node, entity_manager_ptr_->getHdmapUtils(),
74  getROS2Parameter<std::string>("architecture_type", "awf/universe/20240605"))),
75  traffic_controller_ptr_(std::make_shared<traffic::TrafficController>(
76  [this](const std::string & name) { despawn(name); }, entity_manager_ptr_,
77  configuration.auto_sink_entity_types)),
78  clock_pub_(rclcpp::create_publisher<rosgraph_msgs::msg::Clock>(
79  node, "/clock", rclcpp::QoS(rclcpp::KeepLast(1)).best_effort(),
80  rclcpp::PublisherOptionsWithAllocator<AllocatorT>())),
81  debug_marker_pub_(rclcpp::create_publisher<visualization_msgs::msg::MarkerArray>(
82  node, "debug_marker", rclcpp::QoS(100), rclcpp::PublisherOptionsWithAllocator<AllocatorT>())),
83  real_time_factor_subscriber(rclcpp::create_subscription<std_msgs::msg::Float64>(
84  node, "/real_time_factor", rclcpp::QoS(rclcpp::KeepLast(1)).best_effort(),
85  [this](const std_msgs::msg::Float64 & message) {
90  if (message.data >= 0.001) {
91  clock_.realtime_factor = message.data;
92  simulation_api_schema::UpdateStepTimeRequest request;
93  request.set_simulation_step_time(clock_.getStepTime());
94  zeromq_client_.call(request);
95  }
96  })),
97  clock_(node->get_parameter("use_sim_time").as_bool(), std::forward<decltype(xs)>(xs)...),
98  zeromq_client_(
99  simulation_interface::protocol, configuration.simulator_host, getZMQSocketPort(*node))
100  {
101  entity_manager_ptr_->setTrafficLights(traffic_lights_ptr_);
102  setVerbose(configuration.verbose);
103 
104  if (not configuration.standalone_mode) {
105  simulation_api_schema::InitializeRequest request;
106  request.set_initialize_time(clock_.getCurrentSimulationTime());
107  request.set_lanelet2_map_path(configuration.lanelet2_map_path().string());
108  request.set_realtime_factor(clock_.realtime_factor);
109  request.set_step_time(clock_.getStepTime());
111  clock_.getCurrentRosTime(), *request.mutable_initialize_ros_time());
112  if (not zeromq_client_.call(request).result().success()) {
113  throw common::SimulationError("Failed to initialize simulator by InitializeRequest");
114  }
115  }
116  }
117 
118  template <typename ParameterT, typename... Ts>
119  auto getROS2Parameter(Ts &&... xs) const -> decltype(auto)
120  {
121  return getParameter<ParameterT>(node_parameters_, std::forward<Ts>(xs)...);
122  }
123 
124  template <typename Node>
125  int getZMQSocketPort(Node & node)
126  {
127  if (!node.has_parameter("port")) node.declare_parameter("port", 5555);
128  return node.get_parameter("port").as_int();
129  }
130 
131  void closeZMQConnection() { zeromq_client_.closeConnection(); }
132 
133  void setVerbose(const bool verbose);
134 
135  template <typename Pose>
136  auto spawn(
137  const std::string & name, const Pose & pose,
138  const traffic_simulator_msgs::msg::VehicleParameters & parameters,
139  const std::string & behavior = VehicleBehavior::defaultBehavior(),
140  const std::string & model3d = "")
141  {
142  auto register_to_entity_manager = [&]() {
143  if (behavior == VehicleBehavior::autoware()) {
144  return entity_manager_ptr_->isEntityExist(name) or
145  entity_manager_ptr_->spawnEntity<entity::EgoEntity>(
146  name, pose, parameters, getCurrentTime(), configuration, node_parameters_);
147  } else {
148  return entity_manager_ptr_->spawnEntity<entity::VehicleEntity>(
149  name, pose, parameters, getCurrentTime(), behavior);
150  }
151  };
152 
153  auto register_to_environment_simulator = [&]() {
154  if (configuration.standalone_mode) {
155  return true;
156  } else if (!entity_manager_ptr_->isEntityExist(name)) {
157  throw common::SemanticError(
158  "Entity ", name, " can not be registered in simulator - it has not been spawned yet.");
159  } else {
160  simulation_api_schema::SpawnVehicleEntityRequest req;
161  simulation_interface::toProto(parameters, *req.mutable_parameters());
162  req.mutable_parameters()->set_name(name);
163  req.set_asset_key(model3d);
165  entity_manager_ptr_->getEntity(name).getMapPose(), *req.mutable_pose());
166  req.set_is_ego(behavior == VehicleBehavior::autoware());
168  req.set_initial_speed(0.0);
169  return zeromq_client_.call(req).result().success();
170  }
171  };
172 
173  return register_to_entity_manager() and register_to_environment_simulator();
174  }
175 
176  template <typename Pose>
177  auto spawn(
178  const std::string & name, const Pose & pose,
179  const traffic_simulator_msgs::msg::PedestrianParameters & parameters,
181  const std::string & model3d = "")
182  {
183  auto register_to_entity_manager = [&]() {
184  return entity_manager_ptr_->spawnEntity<entity::PedestrianEntity>(
185  name, pose, parameters, getCurrentTime(), behavior);
186  };
187 
188  auto register_to_environment_simulator = [&]() {
189  if (configuration.standalone_mode) {
190  return true;
191  } else if (!entity_manager_ptr_->isEntityExist(name)) {
192  throw common::SemanticError(
193  "Entity ", name, " can not be registered in simulator - it has not been spawned yet.");
194  } else {
195  simulation_api_schema::SpawnPedestrianEntityRequest req;
196  simulation_interface::toProto(parameters, *req.mutable_parameters());
197  req.mutable_parameters()->set_name(name);
198  req.set_asset_key(model3d);
200  entity_manager_ptr_->getEntity(name).getMapPose(), *req.mutable_pose());
201  return zeromq_client_.call(req).result().success();
202  }
203  };
204 
205  return register_to_entity_manager() and register_to_environment_simulator();
206  }
207 
208  template <typename Pose>
209  auto spawn(
210  const std::string & name, const Pose & pose,
211  const traffic_simulator_msgs::msg::MiscObjectParameters & parameters,
212  const std::string & model3d = "")
213  {
214  auto register_to_entity_manager = [&]() {
215  return entity_manager_ptr_->spawnEntity<entity::MiscObjectEntity>(
216  name, pose, parameters, getCurrentTime());
217  };
218 
219  auto register_to_environment_simulator = [&]() {
220  if (configuration.standalone_mode) {
221  return true;
222  } else if (!entity_manager_ptr_->isEntityExist(name)) {
223  throw common::SemanticError(
224  "Entity ", name, " can not be registered in simulator - it has not been spawned yet.");
225  } else {
226  simulation_api_schema::SpawnMiscObjectEntityRequest req;
227  simulation_interface::toProto(parameters, *req.mutable_parameters());
228  req.mutable_parameters()->set_name(name);
229  req.set_asset_key(model3d);
231  entity_manager_ptr_->getEntity(name).getMapPose(), *req.mutable_pose());
232  return zeromq_client_.call(req).result().success();
233  }
234  };
235 
236  return register_to_entity_manager() and register_to_environment_simulator();
237  }
238 
239  bool despawn(const std::string & name);
240  bool despawnEntities();
241 
242  bool checkCollision(
243  const std::string & first_entity_name, const std::string & second_entity_name);
244 
245  auto respawn(
246  const std::string & name, const geometry_msgs::msg::PoseWithCovarianceStamped & new_pose,
247  const geometry_msgs::msg::PoseStamped & goal_pose) -> void;
248 
249  auto attachImuSensor(
250  const std::string &, const simulation_api_schema::ImuSensorConfiguration & configuration)
251  -> bool;
252 
254  const simulation_api_schema::PseudoTrafficLightDetectorConfiguration &);
255 
256  bool attachLidarSensor(const simulation_api_schema::LidarConfiguration &);
257  bool attachLidarSensor(
258  const std::string &, const double lidar_sensor_delay,
260 
261  bool attachDetectionSensor(const simulation_api_schema::DetectionSensorConfiguration &);
263  const std::string &, double detection_sensor_range, bool detect_all_objects_in_range,
264  double pos_noise_stddev, int random_seed, double probability_of_lost,
265  double object_recognition_delay);
266 
267  bool attachOccupancyGridSensor(const simulation_api_schema::OccupancyGridSensorConfiguration &);
268 
269  bool updateFrame();
270 
271  double getCurrentTime() const noexcept { return clock_.getCurrentScenarioTime(); }
272 
273  void startNpcLogic();
274 
293  auto addTrafficSource(
294  const double radius, const double rate, const double speed,
295  const geometry_msgs::msg::Pose & position,
296  const traffic::TrafficSource::Distribution & distribution,
297  const bool allow_spawn_outside_lane = false, const bool require_footprint_fitting = false,
298  const bool random_orientation = false, std::optional<int> random_seed = std::nullopt) -> void;
299 
300  auto getV2ITrafficLights() { return traffic_lights_ptr_->getV2ITrafficLights(); }
301 
303  {
304  return traffic_lights_ptr_->getConventionalTrafficLights();
305  }
306 
307  auto getEntity(const std::string & name) -> entity::EntityBase &;
308 
309  auto getEntity(const std::string & name) const -> const entity::EntityBase &;
310 
311  // clang-format off
312 #define FORWARD_TO_ENTITY_MANAGER(NAME) \
313  \
318  template <typename... Ts> \
319  decltype(auto) NAME(Ts &&... xs) \
320  { \
321  assert(entity_manager_ptr_); \
322  return (*entity_manager_ptr_).NAME(std::forward<decltype(xs)>(xs)...); \
323  } \
324  static_assert(true, "")
325  // clang-format on
326 
335 
336 public:
337 #undef FORWARD_TO_ENTITY_MANAGER
338 
339 private:
340  bool updateTimeInSim();
341 
342  bool updateEntitiesStatusInSim();
343 
344  bool updateTrafficLightsInSim();
345 
346  const Configuration configuration;
347 
348  const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters_;
349 
350  const std::shared_ptr<entity::EntityManager> entity_manager_ptr_;
351 
352  const std::shared_ptr<TrafficLights> traffic_lights_ptr_;
353 
354  const std::shared_ptr<traffic::TrafficController> traffic_controller_ptr_;
355 
356  const rclcpp::Publisher<rosgraph_msgs::msg::Clock>::SharedPtr clock_pub_;
357 
358  const rclcpp::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr debug_marker_pub_;
359 
360  const rclcpp::Subscription<std_msgs::msg::Float64>::SharedPtr real_time_factor_subscriber;
361 
362  SimulationClock clock_;
363 
364  zeromq::MultiClient zeromq_client_;
365 };
366 } // namespace traffic_simulator
367 
368 #endif // TRAFFIC_SIMULATOR__API__API_HPP_
#define FORWARD_TO_ENTITY_MANAGER(NAME)
Definition: api.hpp:312
Definition: api.hpp:63
auto spawn(const std::string &name, const Pose &pose, const traffic_simulator_msgs::msg::MiscObjectParameters &parameters, const std::string &model3d="")
Definition: api.hpp:209
decltype(auto) getEntityPointer(Ts &&... xs)
Forward to arguments to the EntityManager:: getEntityPointer function.
Definition: api.hpp:325
auto getV2ITrafficLights()
Definition: api.hpp:300
decltype(auto) getHdmapUtils(Ts &&... xs)
Forward to arguments to the EntityManager:: getHdmapUtils function.
Definition: api.hpp:327
double getCurrentTime() const noexcept
Definition: api.hpp:271
decltype(auto) getFirstEgoName(Ts &&... xs)
Forward to arguments to the EntityManager:: getFirstEgoName function.
Definition: api.hpp:326
decltype(auto) resetBehaviorPlugin(Ts &&... xs)
Forward to arguments to the EntityManager:: resetBehaviorPlugin function.
Definition: api.hpp:330
decltype(auto) getEgoEntity(Ts &&... xs)
Forward to arguments to the EntityManager:: getEgoEntity function.
Definition: api.hpp:323
auto addTrafficSource(const double radius, const double rate, const double speed, const geometry_msgs::msg::Pose &position, const traffic::TrafficSource::Distribution &distribution, const bool allow_spawn_outside_lane=false, const bool require_footprint_fitting=false, const bool random_orientation=false, std::optional< int > random_seed=std::nullopt) -> void
Add a traffic source to the simulation.
Definition: api.cpp:290
API(NodeT &&node, const Configuration &configuration, Ts &&... xs)
Definition: api.hpp:66
auto getEntity(const std::string &name) -> entity::EntityBase &
Definition: api.cpp:116
void startNpcLogic()
Definition: api.cpp:280
auto getConventionalTrafficLights()
Definition: api.hpp:302
decltype(auto) isEntityExist(Ts &&... xs)
Forward to arguments to the EntityManager:: isEntityExist function.
Definition: api.hpp:328
int getZMQSocketPort(Node &node)
Definition: api.hpp:125
bool checkCollision(const std::string &first_entity_name, const std::string &second_entity_name)
Definition: api.cpp:100
bool attachOccupancyGridSensor(const simulation_api_schema::OccupancyGridSensorConfiguration &)
Definition: api.cpp:165
void setVerbose(const bool verbose)
Definition: api.cpp:32
auto getROS2Parameter(Ts &&... xs) const -> decltype(auto)
Definition: api.hpp:119
auto spawn(const std::string &name, const Pose &pose, const traffic_simulator_msgs::msg::VehicleParameters &parameters, const std::string &behavior=VehicleBehavior::defaultBehavior(), const std::string &model3d="")
Definition: api.hpp:136
bool attachDetectionSensor(const simulation_api_schema::DetectionSensorConfiguration &)
Definition: api.cpp:142
decltype(auto) isNpcLogicStarted(Ts &&... xs)
Forward to arguments to the EntityManager:: isNpcLogicStarted function.
Definition: api.hpp:329
auto spawn(const std::string &name, const Pose &pose, const traffic_simulator_msgs::msg::PedestrianParameters &parameters, const std::string &behavior=PedestrianBehavior::defaultBehavior(), const std::string &model3d="")
Definition: api.hpp:177
auto respawn(const std::string &name, const geometry_msgs::msg::PoseWithCovarianceStamped &new_pose, const geometry_msgs::msg::PoseStamped &goal_pose) -> void
Definition: api.cpp:55
void closeZMQConnection()
Definition: api.hpp:131
decltype(auto) getEntityNames(Ts &&... xs)
Forward to arguments to the EntityManager:: getEntityNames function.
Definition: api.hpp:324
bool attachPseudoTrafficLightDetector(const simulation_api_schema::PseudoTrafficLightDetectorConfiguration &)
Definition: api.cpp:134
bool despawnEntities()
Definition: api.cpp:48
bool despawn(const std::string &name)
Definition: api.cpp:34
bool attachLidarSensor(const simulation_api_schema::LidarConfiguration &)
Definition: api.cpp:177
auto attachImuSensor(const std::string &, const simulation_api_schema::ImuSensorConfiguration &configuration) -> bool
Definition: api.cpp:126
bool updateFrame()
Definition: api.cpp:253
Definition: simulation_clock.hpp:24
auto getCurrentRosTime() -> rclcpp::Time
Definition: simulation_clock.cpp:41
double realtime_factor
Definition: simulation_clock.hpp:49
auto getCurrentScenarioTime() const
Definition: simulation_clock.hpp:32
auto getCurrentSimulationTime() const
Definition: simulation_clock.hpp:37
auto getStepTime() const
Definition: simulation_clock.hpp:39
Definition: traffic_lights.hpp:132
Definition: ego_entity.hpp:35
Definition: entity_base.hpp:51
Definition: misc_object_entity.hpp:27
Definition: pedestrian_entity.hpp:34
Definition: vehicle_entity.hpp:37
std::vector< std::tuple< VehicleOrPedestrianParameter, std::string, std::string, double > > Distribution
Definition: traffic_source.hpp:69
Definition: zmq_multi_client.hpp:33
void closeConnection()
Definition: zmq_multi_client.cpp:33
auto call(const simulation_api_schema::SimulationRequest &) -> simulation_api_schema::SimulationResponse
Definition: zmq_multi_client.cpp:43
void toProto(const geometry_msgs::msg::Point &p, geometry_msgs::Point &proto)
Definition: conversions.cpp:22
const TransportProtocol protocol
Definition: constants.hpp:30
Definition: lanelet_wrapper.hpp:39
LidarType
Definition: helper.hpp:141
geometry_msgs::msg::Pose Pose
Definition: lanelet_map.hpp:30
geometry_msgs::msg::Pose Pose
Definition: lanelet_wrapper.hpp:65
geometry_msgs::msg::PoseStamped PoseStamped
Definition: lanelet_wrapper.hpp:66
Definition: api.hpp:48
Definition: junit5.hpp:25
std::string string
Definition: junit5.hpp:26
Although there were no syntactic errors in the description of the scenario, differences in meaning an...
Definition: exception.hpp:44
A problem occurred that interfered with the continuation of the simulation.
Definition: exception.hpp:47
Definition: configuration.hpp:31
auto lanelet2_map_path() const -> boost::filesystem::path
Definition: configuration.hpp:152
bool verbose
Definition: configuration.hpp:36
const bool standalone_mode
Definition: configuration.hpp:40
static auto autoware() noexcept -> const std::string &
Definition: api.hpp:51
static auto defaultBehavior() noexcept -> const std::string &
Definition: pedestrian_entity.hpp:56
static auto defaultBehavior() -> const std::string &
Definition: vehicle_entity.hpp:59
class definition for the traffic controller