scenario_simulator_v2 C++ API
traffic_lights.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__TRAFFIC_LIGHTS__TRAFFIC_LIGHTS_HPP_
16 #define TRAFFIC_SIMULATOR__TRAFFIC_LIGHTS__TRAFFIC_LIGHTS_HPP_
17 
18 // This message will be deleted in the future
19 #if __has_include(<autoware_perception_msgs/msg/traffic_signal_array.hpp>)
20 #include <autoware_perception_msgs/msg/traffic_signal_array.hpp>
21 #endif
22 
23 #if __has_include(<autoware_perception_msgs/msg/traffic_light_group_array.hpp>)
24 #include <autoware_perception_msgs/msg/traffic_light_group_array.hpp>
25 #endif
26 
27 #include <algorithm>
28 #include <set>
31 
32 namespace traffic_simulator
33 {
35 {
36 public:
37  template <typename NodeTypePointer>
39  const NodeTypePointer & node_ptr, const std::shared_ptr<hdmap_utils::HdMapUtils> & hdmap_utils)
40  : TrafficLightsBase(node_ptr, hdmap_utils),
41  backward_compatible_publisher_ptr_(
42  std::make_unique<TrafficLightPublisher<traffic_simulator_msgs::msg::TrafficLightArrayV1>>(
43  node_ptr, "/simulation/traffic_lights"))
44  {
45  }
46 
47  ~ConventionalTrafficLights() override = default;
48 
49 private:
50  auto update() const -> void override
51  {
52  backward_compatible_publisher_ptr_->publish(
55  marker_publisher_ptr_->deleteMarkers();
56  }
58  }
59 
60  const std::unique_ptr<TrafficLightPublisherBase> backward_compatible_publisher_ptr_;
61 };
62 
64 {
65 public:
66  explicit DetectedTrafficLights(const std::shared_ptr<hdmap_utils::HdMapUtils> & hdmap_utils)
67  : hdmap_utils_(hdmap_utils)
68  {
69  }
70 
71  auto setState(const lanelet::Id lanelet_id, const std::string & state) -> void
72  {
73  clearState(lanelet_id);
74  addState(lanelet_id, state);
75  }
76 
77  auto addState(const lanelet::Id lanelet_id, const std::string & state) -> void
78  {
79  auto [iter, inserted] =
80  detected_traffic_lights_.try_emplace(lanelet_id, lanelet_id, *hdmap_utils_);
81  iter->second.set(state);
82  }
83 
84  auto clearState(const lanelet::Id lanelet_id) -> bool
85  {
86  return detected_traffic_lights_.erase(lanelet_id) > 0;
87  }
88 
89  auto empty() const -> bool { return detected_traffic_lights_.empty(); }
90 
91  auto apply(simulation_api_schema::UpdateTrafficLightsRequest & request) const -> void
92  {
93  for (const auto & [lanelet_id, detected_light] : detected_traffic_lights_) {
94  if (auto matched_state = std::find_if(
95  request.mutable_states()->begin(), request.mutable_states()->end(),
96  [lanelet_id](const auto & state) { return state.id() == lanelet_id; });
97  matched_state != request.mutable_states()->end()) {
98  // Only update traffic_light_status (bulbs), preserve relation_ids
99  auto detected_signal = static_cast<simulation_api_schema::TrafficSignal>(detected_light);
100  matched_state->clear_traffic_light_status();
101  for (const auto & status : detected_signal.traffic_light_status()) {
102  *matched_state->add_traffic_light_status() = status;
103  }
104  } else {
105  // add ground-truth-less detected traffic light
106  *request.add_states() = static_cast<simulation_api_schema::TrafficSignal>(detected_light);
107  }
108  }
109  }
110 
111 private:
112  std::map<lanelet::Id, TrafficLight> detected_traffic_lights_;
113 
114  std::shared_ptr<hdmap_utils::HdMapUtils> hdmap_utils_;
115 };
116 
118 {
119 public:
120  template <typename NodeTypePointer>
122  const NodeTypePointer & node_ptr, const std::shared_ptr<hdmap_utils::HdMapUtils> & hdmap_utils,
123  const std::string & architecture_type)
124  : TrafficLightsBase(node_ptr, hdmap_utils),
125  publisher_ptr_(makePublisher(
126  node_ptr, architecture_type,
127  "/perception/traffic_light_recognition/external/traffic_signals")),
128  legacy_topic_publisher_ptr_(makePublisher(node_ptr, architecture_type, "/v2x/traffic_signals"))
129  {
130  }
131 
132  ~V2ITrafficLights() override = default;
133 
134  auto setDetectedTrafficLights(std::shared_ptr<DetectedTrafficLights> detected) -> void
135  {
136  detected_ = detected;
137  }
138 
140  const lanelet::Id lanelet_id, const std::string & state, double time_ahead_seconds) -> void;
141 
142  auto clearTrafficLightsStatePredictions() -> void;
143 
144 private:
145  auto update() const -> void override
146  {
147  const auto now = clock_ptr_->now();
148  auto request = generateUpdateTrafficLightsRequest();
149  if (detected_) {
150  detected_->apply(request);
151  }
152  publisher_ptr_->publish(now, request, &predictions_);
153  legacy_topic_publisher_ptr_->publish(now, request, &predictions_);
154  if (isAnyTrafficLightChanged()) {
155  marker_publisher_ptr_->deleteMarkers();
156  }
158  }
159 
160  template <typename NodeTypePointer>
161  auto makePublisher(
162  const NodeTypePointer & node_ptr, const std::string & architecture_type,
163  const std::string & topic_name) -> std::unique_ptr<TrafficLightPublisherBase>
164  {
165  /*
166  V2ITrafficLights in TrafficSimulator publishes using architecture-independent topics ("awf/universe..."):
167  "/v2x/traffic_signals" and "/perception/traffic_light_recognition/external/traffic_signals"
168 
169  TrafficLightsDetector in SimpleSensorSimulator publishes using architecture-dependent topics:
170  "/perception/traffic_light_recognition/internal/traffic_signals" for >= "awf/universe/20230906"
171  "/perception/traffic_light_recognition/traffic_signals" for "awf/universe"
172  */
173  if (architecture_type == "awf/universe") {
174  throw common::SemanticError(
175  "This version of scenario_simulator_v2 does not support ", std::quoted(architecture_type),
176  " as ", std::quoted("architecture_type"), ". Please use older version.");
177 #if __has_include(<autoware_perception_msgs/msg/traffic_signal_array.hpp>)
178  } else if (architecture_type <= "awf/universe/20230906") {
179  return std::make_unique<
180  TrafficLightPublisher<autoware_perception_msgs::msg::TrafficSignalArray>>(
181  node_ptr, topic_name);
182 #endif
183 #if __has_include(<autoware_perception_msgs/msg/traffic_light_group_array.hpp>)
184  } else if (architecture_type >= "awf/universe/20240605") {
185  return std::make_unique<
186  TrafficLightPublisher<autoware_perception_msgs::msg::TrafficLightGroupArray>>(
187  node_ptr, topic_name);
188 #endif
189  } else {
190  throw common::SemanticError(
191  "Unexpected architecture_type ", std::quoted(architecture_type),
192  " given for V2I traffic lights simulation.");
193  }
194  }
195 
196  const std::unique_ptr<TrafficLightPublisherBase> publisher_ptr_;
197 
198  const std::unique_ptr<TrafficLightPublisherBase> legacy_topic_publisher_ptr_;
199 
200  std::shared_ptr<DetectedTrafficLights> detected_;
201 
202  TrafficLightStatePredictions predictions_;
203 };
204 
205 template <typename GroundTruthType>
207 {
208 public:
209  template <typename NodeTypePointer, typename... Args>
211  const NodeTypePointer & node_ptr, const std::shared_ptr<hdmap_utils::HdMapUtils> & hdmap_utils,
212  Args &&... args)
213  : ground_truth_(
214  std::make_shared<GroundTruthType>(node_ptr, hdmap_utils, std::forward<Args>(args)...)),
215  detected_(std::make_shared<DetectedTrafficLights>(hdmap_utils))
216  {
217  }
218 
219  auto getGroundTruth() const -> std::shared_ptr<GroundTruthType> { return ground_truth_; }
220 
221  auto getDetected() const -> std::shared_ptr<DetectedTrafficLights> { return detected_; }
222 
223  auto hasDetectedChanges() const -> bool { return not detected_->empty(); }
224 
225  auto generateUpdateRequest() const -> simulation_api_schema::UpdateTrafficLightsRequest
226  {
227  auto request = ground_truth_->generateUpdateTrafficLightsRequest();
228  detected_->apply(request);
229  return request;
230  }
231 
232 private:
233  std::shared_ptr<GroundTruthType> ground_truth_;
234 
235  std::shared_ptr<DetectedTrafficLights> detected_;
236 };
237 
239 {
240 public:
241  template <typename NodeTypePointer>
242  explicit TrafficLights(
243  const NodeTypePointer & node_ptr, const std::shared_ptr<hdmap_utils::HdMapUtils> & hdmap_utils,
244  const std::string & architecture_type)
245  : conventional_channel_(node_ptr, hdmap_utils),
246  v2i_channel_(node_ptr, hdmap_utils, architecture_type),
247  hdmap_utils_(hdmap_utils)
248  {
249  v2i_channel_.getGroundTruth()->setDetectedTrafficLights(v2i_channel_.getDetected());
250 
251  conventional_channel_.getGroundTruth()->registerStateChangeCallback(
252  [this, v2i = v2i_channel_.getGroundTruth()](
253  lanelet::Id lanelet_id, const std::string & state,
255  if (v2i_enabled_traffic_lights_.count(lanelet_id) > 0) {
256  switch (change_type) {
257  case TrafficLightsBase::StateChangeType::SET:
258  v2i->setTrafficLightsState(lanelet_id, state);
259  break;
260  case TrafficLightsBase::StateChangeType::CLEAR:
261  v2i->clearTrafficLightsState(lanelet_id);
262  break;
263  case TrafficLightsBase::StateChangeType::ADD:
264  v2i->addTrafficLightsState(lanelet_id, state);
265  break;
266  }
267  }
268  });
269  }
270 
271  auto setV2IFeature(const lanelet::Id lanelet_id, const bool enabled) -> void
272  {
273  if (hdmap_utils_->isTrafficLightRegulatoryElement(lanelet_id)) {
274  // relation ID -> convert to way IDs
275  const auto regulatory_element = hdmap_utils_->getTrafficLightRegulatoryElement(lanelet_id);
276  for (const auto & ref_member :
277  regulatory_element->getParameters<lanelet::ConstLineString3d>("refers")) {
278  setV2IFeature(ref_member.id(), enabled);
279  }
280  } else if (hdmap_utils_->isTrafficLight(lanelet_id)) {
281  // way ID -> use directly
282  if (enabled) {
283  v2i_enabled_traffic_lights_.insert(lanelet_id);
284  } else {
285  v2i_enabled_traffic_lights_.erase(lanelet_id);
286  }
287  }
288  }
289 
290  auto isAnyTrafficLightChanged() -> bool;
291 
292  auto startTrafficLightsUpdate(
293  const double conventional_traffic_light_update_rate,
294  const double v2i_traffic_lights_update_rate) -> void;
295 
296  auto getConventionalTrafficLights() const -> std::shared_ptr<ConventionalTrafficLights>;
297 
298  auto getV2ITrafficLights() const -> std::shared_ptr<V2ITrafficLights>;
299 
300  auto getConventionalDetectedTrafficLights() const -> std::shared_ptr<DetectedTrafficLights>;
301 
302  auto getV2IDetectedTrafficLights() const -> std::shared_ptr<DetectedTrafficLights>;
303 
304  auto generateConventionalUpdateRequest() const
305  -> simulation_api_schema::UpdateTrafficLightsRequest;
306 
307  auto isV2ITrafficLightEnabled(const lanelet::Id lanelet_id) const -> bool;
308 
309 private:
310  TrafficLightsChannel<ConventionalTrafficLights> conventional_channel_;
311 
313 
314  std::set<lanelet::Id> v2i_enabled_traffic_lights_;
315 
316  std::shared_ptr<hdmap_utils::HdMapUtils> hdmap_utils_;
317 };
318 } // namespace traffic_simulator
319 #endif // TRAFFIC_SIMULATOR__TRAFFIC_LIGHTS__TRAFFIC_LIGHTS_HPP_
Definition: traffic_lights.hpp:35
ConventionalTrafficLights(const NodeTypePointer &node_ptr, const std::shared_ptr< hdmap_utils::HdMapUtils > &hdmap_utils)
Definition: traffic_lights.hpp:38
Definition: traffic_lights.hpp:64
auto setState(const lanelet::Id lanelet_id, const std::string &state) -> void
Definition: traffic_lights.hpp:71
auto clearState(const lanelet::Id lanelet_id) -> bool
Definition: traffic_lights.hpp:84
auto addState(const lanelet::Id lanelet_id, const std::string &state) -> void
Definition: traffic_lights.hpp:77
auto empty() const -> bool
Definition: traffic_lights.hpp:89
auto apply(simulation_api_schema::UpdateTrafficLightsRequest &request) const -> void
Definition: traffic_lights.hpp:91
DetectedTrafficLights(const std::shared_ptr< hdmap_utils::HdMapUtils > &hdmap_utils)
Definition: traffic_lights.hpp:66
Definition: traffic_light_publisher.hpp:40
Definition: traffic_lights_base.hpp:44
StateChangeType
Definition: traffic_lights_base.hpp:47
auto isAnyTrafficLightChanged() const -> bool
Definition: traffic_lights_base.cpp:30
auto generateUpdateTrafficLightsRequest() const -> simulation_api_schema::UpdateTrafficLightsRequest
Definition: traffic_lights_base.cpp:112
const rclcpp::Clock::SharedPtr clock_ptr_
Definition: traffic_lights_base.hpp:114
const std::unique_ptr< TrafficLightMarkerPublisher > marker_publisher_ptr_
Definition: traffic_lights_base.hpp:117
std::unordered_map< lanelet::Id, TrafficLight > traffic_lights_map_
Definition: traffic_lights_base.hpp:116
Definition: traffic_lights.hpp:207
auto getGroundTruth() const -> std::shared_ptr< GroundTruthType >
Definition: traffic_lights.hpp:219
TrafficLightsChannel(const NodeTypePointer &node_ptr, const std::shared_ptr< hdmap_utils::HdMapUtils > &hdmap_utils, Args &&... args)
Definition: traffic_lights.hpp:210
auto getDetected() const -> std::shared_ptr< DetectedTrafficLights >
Definition: traffic_lights.hpp:221
auto generateUpdateRequest() const -> simulation_api_schema::UpdateTrafficLightsRequest
Definition: traffic_lights.hpp:225
auto hasDetectedChanges() const -> bool
Definition: traffic_lights.hpp:223
Definition: traffic_lights.hpp:239
TrafficLights(const NodeTypePointer &node_ptr, const std::shared_ptr< hdmap_utils::HdMapUtils > &hdmap_utils, const std::string &architecture_type)
Definition: traffic_lights.hpp:242
auto setV2IFeature(const lanelet::Id lanelet_id, const bool enabled) -> void
Definition: traffic_lights.hpp:271
Definition: traffic_lights.hpp:118
auto addTrafficLightsStatePrediction(const lanelet::Id lanelet_id, const std::string &state, double time_ahead_seconds) -> void
Definition: traffic_lights.cpp:67
V2ITrafficLights(const NodeTypePointer &node_ptr, const std::shared_ptr< hdmap_utils::HdMapUtils > &hdmap_utils, const std::string &architecture_type)
Definition: traffic_lights.hpp:121
auto clearTrafficLightsStatePredictions() -> void
Definition: traffic_lights.cpp:107
~V2ITrafficLights() override=default
auto setDetectedTrafficLights(std::shared_ptr< DetectedTrafficLights > detected) -> void
Definition: traffic_lights.hpp:134
Definition: cache.hpp:28
Definition: lanelet_wrapper.hpp:40
Definition: operators.hpp:25
Definition: api.hpp:32
std::unordered_map< lanelet::Id, std::vector< std::pair< rclcpp::Time, std::vector< simulation_api_schema::TrafficLight > >> > TrafficLightStatePredictions
Definition: traffic_lights_base.hpp:35
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