maliput/api/rules/mod.rs
1// BSD 3-Clause License
2//
3// Copyright (c) 2024, Woven by Toyota.
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are met:
8//
9// * Redistributions of source code must retain the above copyright notice, this
10// list of conditions and the following disclaimer.
11//
12// * Redistributions in binary form must reproduce the above copyright notice,
13// this list of conditions and the following disclaimer in the documentation
14// and/or other materials provided with the distribution.
15//
16// * Neither the name of the copyright holder nor the names of its
17// contributors may be used to endorse or promote products derived from
18// this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31use crate::common::MaliputError;
32use strum_macros::{Display, IntoStaticStr};
33
34/// Interface for accessing the [TrafficLight] in the [super::RoadNetwork]
35pub struct TrafficLightBook<'a> {
36 pub(super) traffic_light_book: &'a maliput_sys::api::rules::ffi::TrafficLightBook,
37}
38
39impl<'a> TrafficLightBook<'a> {
40 /// Gets all the [TrafficLight]s in the [TrafficLightBook]
41 ///
42 /// # Returns
43 /// A vector of [TrafficLight]s
44 pub fn traffic_lights(&self) -> Vec<TrafficLight<'_>> {
45 let traffic_lights_cpp = maliput_sys::api::rules::ffi::TrafficLightBook_TrafficLights(self.traffic_light_book);
46 traffic_lights_cpp
47 .into_iter()
48 .map(|tl| TrafficLight {
49 traffic_light: unsafe { tl.traffic_light.as_ref().expect("") },
50 })
51 .collect::<Vec<TrafficLight>>()
52 }
53
54 /// Gets a [TrafficLight] by its id.
55 ///
56 /// # Arguments
57 /// * `id` - The id of the [TrafficLight].
58 ///
59 /// # Returns
60 /// The [TrafficLight] with the given id.
61 /// If no [TrafficLight] is found with the given id, return None.
62 pub fn get_traffic_light(&self, id: &String) -> Option<TrafficLight<'_>> {
63 let traffic_light = maliput_sys::api::rules::ffi::TrafficLightBook_GetTrafficLight(self.traffic_light_book, id);
64 if traffic_light.is_null() {
65 return None;
66 }
67 Some(TrafficLight {
68 traffic_light: unsafe {
69 traffic_light
70 .as_ref()
71 .expect("Unable to get underlying traffic light pointer")
72 },
73 })
74 }
75}
76
77/// Models a traffic light. A traffic light is a physical signaling device
78/// typically located at road intersections. It contains one or more groups of
79/// light bulbs with varying colors and shapes. The lighting patterns of the
80/// bulbs signify right-of-way rule information to the agents navigating the
81/// intersection (e.g., vehicles, bicyclists, pedestrians, etc.). Typically, an
82/// intersection will be managed by multiple traffic lights.
83///
84/// Note that traffic lights are physical manifestations of underlying
85/// right-of-way rules and thus naturally have lower signal-to-noise ratio
86/// relative to the underlying rules. Thus, oracular agents should directly use
87/// the underlying right-of-way rules instead of traffic lights when navigating
88/// intersections. TrafficLight exists for testing autonomous vehicles that do
89/// not have access to right-of-way rules.
90pub struct TrafficLight<'a> {
91 pub traffic_light: &'a maliput_sys::api::rules::ffi::TrafficLight,
92}
93
94impl<'a> TrafficLight<'a> {
95 /// Get the id of the [TrafficLight].
96 ///
97 /// # Returns
98 /// The id of the [TrafficLight].
99 pub fn id(&self) -> String {
100 maliput_sys::api::rules::ffi::TrafficLight_id(self.traffic_light)
101 }
102
103 /// Get the position of the [TrafficLight] in the road network.
104 ///
105 /// # Returns
106 /// An [crate::api::InertialPosition] representing the position of the [TrafficLight] in the road network.
107 pub fn position_road_network(&self) -> crate::api::InertialPosition {
108 let inertial_position = maliput_sys::api::rules::ffi::TrafficLight_position_road_network(self.traffic_light);
109 crate::api::InertialPosition { ip: inertial_position }
110 }
111
112 /// Get the orientation of the [TrafficLight] in the road network.
113 ///
114 /// # Returns
115 /// An [crate::api::Rotation] representing the orientation of the [TrafficLight] in the road network.
116 pub fn orientation_road_network(&self) -> crate::api::Rotation {
117 let rotation = maliput_sys::api::rules::ffi::TrafficLight_orientation_road_network(self.traffic_light);
118 crate::api::Rotation { r: rotation }
119 }
120
121 /// Get the bulb groups of the [TrafficLight].
122 ///
123 /// # Returns
124 /// A vector of [BulbGroup]s in the [TrafficLight].
125 /// If the [TrafficLight] has no bulb groups, return an empty vector.
126 pub fn bulb_groups(&self) -> Vec<BulbGroup<'_>> {
127 let bulb_groups_cpp = maliput_sys::api::rules::ffi::TrafficLight_bulb_groups(self.traffic_light);
128 bulb_groups_cpp
129 .into_iter()
130 .map(|bg| BulbGroup {
131 bulb_group: unsafe { bg.bulb_group.as_ref().expect("") },
132 })
133 .collect::<Vec<BulbGroup>>()
134 }
135
136 /// Get a [BulbGroup] by its id.
137 ///
138 /// # Arguments
139 /// * `id` - The id of the [BulbGroup].
140 ///
141 /// # Returns
142 /// The [BulbGroup] with the given id.
143 /// If no [BulbGroup] is found with the given id, return None.
144 pub fn get_bulb_group(&self, id: &String) -> Option<BulbGroup<'_>> {
145 let bulb_group = maliput_sys::api::rules::ffi::TrafficLight_GetBulbGroup(self.traffic_light, id);
146 if bulb_group.is_null() {
147 return None;
148 }
149 Some(BulbGroup {
150 bulb_group: unsafe {
151 bulb_group
152 .as_ref()
153 .expect("Unable to get underlying bulb group pointer")
154 },
155 })
156 }
157}
158
159#[derive(Debug, Copy, Clone, PartialEq, Eq)]
160/// Defines the possible bulb colors.
161pub enum BulbColor {
162 Red,
163 Yellow,
164 Green,
165}
166
167#[derive(Debug, Copy, Clone, PartialEq, Eq)]
168/// Defines the possible bulb types.
169pub enum BulbType {
170 Round,
171 Arrow,
172}
173
174#[derive(Debug, Copy, Clone, PartialEq, Eq)]
175/// Defines the possible bulb types.
176pub enum BulbState {
177 Off,
178 On,
179 Blinking,
180}
181
182/// Models a bulb within a bulb group.
183pub struct Bulb<'a> {
184 pub bulb: &'a maliput_sys::api::rules::ffi::Bulb,
185}
186
187impl Bulb<'_> {
188 /// Returns this Bulb instance's unique identifier.
189 ///
190 /// # Returns
191 /// A [UniqueBulbId] representing the unique identifier of the [Bulb].
192 pub fn unique_id(&self) -> UniqueBulbId {
193 UniqueBulbId {
194 unique_bulb_id: maliput_sys::api::rules::ffi::Bulb_unique_id(self.bulb),
195 }
196 }
197
198 /// Get the id of the [Bulb].
199 ///
200 /// # Returns
201 /// The id of the [Bulb].
202 pub fn id(&self) -> String {
203 maliput_sys::api::rules::ffi::Bulb_id(self.bulb)
204 }
205
206 /// Get the color of the [Bulb].
207 ///
208 /// # Returns
209 /// The [BulbColor].
210 pub fn color(&self) -> BulbColor {
211 let color = self.bulb.color();
212 match *color {
213 maliput_sys::api::rules::ffi::BulbColor::kRed => BulbColor::Red,
214 maliput_sys::api::rules::ffi::BulbColor::kYellow => BulbColor::Yellow,
215 maliput_sys::api::rules::ffi::BulbColor::kGreen => BulbColor::Green,
216 _ => panic!("Invalid bulb color"),
217 }
218 }
219
220 /// Get the type of the [Bulb].
221 ///
222 /// # Returns
223 /// The [BulbType].
224 pub fn bulb_type(&self) -> BulbType {
225 let bulb_type = maliput_sys::api::rules::ffi::Bulb_type(self.bulb);
226 match *bulb_type {
227 maliput_sys::api::rules::ffi::BulbType::kRound => BulbType::Round,
228 maliput_sys::api::rules::ffi::BulbType::kArrow => BulbType::Arrow,
229 _ => panic!("Invalid bulb type"),
230 }
231 }
232
233 /// Get the position of the [Bulb] in the bulb group.
234 ///
235 /// # Returns
236 /// An [crate::api::InertialPosition] representing the position of the [Bulb] in the bulb group.
237 pub fn position_bulb_group(&self) -> crate::api::InertialPosition {
238 let inertial_position = maliput_sys::api::rules::ffi::Bulb_position_bulb_group(self.bulb);
239 crate::api::InertialPosition { ip: inertial_position }
240 }
241
242 /// Get the orientation of the [Bulb] in the bulb group.
243 ///
244 /// # Returns
245 /// An [crate::api::Rotation] representing the orientation of the [Bulb] in the bulb group.
246 pub fn orientation_bulb_group(&self) -> crate::api::Rotation {
247 let rotation = maliput_sys::api::rules::ffi::Bulb_orientation_bulb_group(self.bulb);
248 crate::api::Rotation { r: rotation }
249 }
250
251 /// Returns the arrow's orientation. Only applicable if [Bulb::bulb_type] returns [BulbType::Arrow].
252 ///
253 /// # Returns
254 /// An `Option<f64>` representing the orientation of the arrow in radians.
255 pub fn arrow_orientation_rad(&self) -> Option<f64> {
256 let arrow_orientation = maliput_sys::api::rules::ffi::Bulb_arrow_orientation_rad(self.bulb);
257 if arrow_orientation.is_null() {
258 return None;
259 }
260 Some(arrow_orientation.value)
261 }
262
263 /// Gets the possible states of the [Bulb].
264 ///
265 /// # Returns
266 /// A vector of [BulbState]s representing the possible states of the [Bulb].
267 pub fn states(&self) -> Vec<BulbState> {
268 let states_cpp = maliput_sys::api::rules::ffi::Bulb_states(self.bulb);
269 states_cpp
270 .into_iter()
271 .map(Bulb::_from_cpp_state_to_rust_state)
272 .collect::<Vec<BulbState>>()
273 }
274
275 /// Gets the default state of the [Bulb].
276 ///
277 /// # Returns
278 /// A [BulbState] representing the default state of the [Bulb].
279 pub fn get_default_state(&self) -> BulbState {
280 let default_state = self.bulb.GetDefaultState();
281 Bulb::_from_cpp_state_to_rust_state(&default_state)
282 }
283
284 /// Check if the given state is possible valid for the [Bulb].
285 ///
286 /// # Arguments
287 /// * `state` - The [BulbState] to check.
288 ///
289 /// # Returns
290 /// A boolean indicating whether the given state is valid for the [Bulb].
291 pub fn is_valid_state(&self, state: &BulbState) -> bool {
292 self.bulb.IsValidState(&Bulb::_from_rust_state_to_cpp_state(state))
293 }
294
295 /// Returns the bounding box of the bulb.
296 ///
297 /// # Returns
298 /// A tuple containing the minimum and maximum points of the bounding box.
299 pub fn bounding_box(&self) -> (crate::math::Vector3, crate::math::Vector3) {
300 let min = maliput_sys::api::rules::ffi::Bulb_bounding_box_min(self.bulb);
301 let max = maliput_sys::api::rules::ffi::Bulb_bounding_box_max(self.bulb);
302 (crate::math::Vector3 { v: min }, crate::math::Vector3 { v: max })
303 }
304
305 /// Returns the parent [BulbGroup] of the bulb.
306 ///
307 /// # Returns
308 /// The parent [BulbGroup] of the bulb.
309 /// If the bulb is not part of any group, return None.
310 pub fn bulb_group(&self) -> BulbGroup<'_> {
311 BulbGroup {
312 bulb_group: unsafe {
313 maliput_sys::api::rules::ffi::Bulb_bulb_group(self.bulb)
314 .as_ref()
315 .expect("Unable to get underlying bulb group pointer. The Bulb might not be part of any BulbGroup.")
316 },
317 }
318 }
319
320 /// Convert from the C++ BulbState to the Rust BulbState
321 /// It is expected to be used only internally.
322 ///
323 /// # Arguments
324 /// * `cpp_bulb_state` - The C++ BulbState
325 ///
326 /// # Returns
327 /// The Rust BulbState
328 ///
329 /// # Panics
330 /// If the C++ BulbState is invalid.
331 fn _from_cpp_state_to_rust_state(cpp_bulb_state: &maliput_sys::api::rules::ffi::BulbState) -> BulbState {
332 match *cpp_bulb_state {
333 maliput_sys::api::rules::ffi::BulbState::kOff => BulbState::Off,
334 maliput_sys::api::rules::ffi::BulbState::kOn => BulbState::On,
335 maliput_sys::api::rules::ffi::BulbState::kBlinking => BulbState::Blinking,
336 _ => panic!("Invalid bulb state"),
337 }
338 }
339
340 /// Convert from the Rust BulbState to the C++ BulbState
341 /// It is expected to be used only internally.
342 ///
343 /// # Arguments
344 /// * `rust_bulb_state` - The Rust BulbState
345 ///
346 /// # Returns
347 /// The C++ BulbState
348 fn _from_rust_state_to_cpp_state(rust_bulb_state: &BulbState) -> maliput_sys::api::rules::ffi::BulbState {
349 match rust_bulb_state {
350 BulbState::Off => maliput_sys::api::rules::ffi::BulbState::kOff,
351 BulbState::On => maliput_sys::api::rules::ffi::BulbState::kOn,
352 BulbState::Blinking => maliput_sys::api::rules::ffi::BulbState::kBlinking,
353 }
354 }
355}
356
357/// Models a group of bulbs within a traffic light. All of the bulbs within a
358/// group should share the same approximate orientation. However, this is not
359/// programmatically enforced.
360/// About the bulb group pose:
361/// - The position of the bulb group is defined as the linear offset of this bulb group's frame
362/// relative to the frame of the traffic light that contains it. The origin of
363/// this bulb group's frame should approximate the bulb group's CoM.
364/// - The orientation of the bulb group is defined as the rotational offset of this bulb
365/// group's frame relative to the frame of the traffic light that contains it.
366/// The +Z axis should align with the bulb group's "up" direction, and the +X
367/// axis should point in the direction that the bulb group is facing.
368/// Following a right-handed coordinate frame, the +Y axis should point left
369/// when facing the +X direction.
370pub struct BulbGroup<'a> {
371 pub bulb_group: &'a maliput_sys::api::rules::ffi::BulbGroup,
372}
373
374impl BulbGroup<'_> {
375 /// Returns this BulbGroup instance's unique identifier.
376 ///
377 /// # Returns
378 /// A [UniqueBulbGroupId] representing the unique identifier of the [BulbGroup].
379 pub fn unique_id(&self) -> UniqueBulbGroupId {
380 UniqueBulbGroupId {
381 unique_bulb_group_id: maliput_sys::api::rules::ffi::BulbGroup_unique_id(self.bulb_group),
382 }
383 }
384
385 /// Gets the id of the [BulbGroup].
386 ///
387 /// # Returns
388 /// The id of the [BulbGroup].
389 pub fn id(&self) -> String {
390 maliput_sys::api::rules::ffi::BulbGroup_id(self.bulb_group)
391 }
392
393 /// Gets the position of the [BulbGroup] in the traffic light.
394 ///
395 /// # Returns
396 /// An [crate::api::InertialPosition] representing the position of the [BulbGroup] in the traffic light.
397 pub fn position_traffic_light(&self) -> crate::api::InertialPosition {
398 let inertial_position = maliput_sys::api::rules::ffi::BulbGroup_position_traffic_light(self.bulb_group);
399 crate::api::InertialPosition { ip: inertial_position }
400 }
401
402 /// Gets the orientation of the [BulbGroup] in the traffic light.
403 ///
404 /// # Returns
405 /// An [crate::api::Rotation] representing the orientation of the [BulbGroup] in the traffic light.
406 pub fn orientation_traffic_light(&self) -> crate::api::Rotation {
407 let rotation = maliput_sys::api::rules::ffi::BulbGroup_orientation_traffic_light(self.bulb_group);
408 crate::api::Rotation { r: rotation }
409 }
410
411 /// Returns the bulbs in the bulb group.
412 ///
413 /// # Returns
414 /// A vector of [Bulb]s in the bulb group.
415 pub fn bulbs(&self) -> Vec<Bulb<'_>> {
416 let bulbs_cpp = maliput_sys::api::rules::ffi::BulbGroup_bulbs(self.bulb_group);
417 bulbs_cpp
418 .into_iter()
419 .map(|b| Bulb {
420 bulb: unsafe { b.bulb.as_ref().expect("") },
421 })
422 .collect::<Vec<Bulb>>()
423 }
424
425 /// Gets a [Bulb] by its id
426 ///
427 /// # Arguments
428 /// * `id` - The id of the [Bulb].
429 ///
430 /// # Returns
431 /// The [Bulb] with the given id.
432 /// If no [Bulb] is found with the given id, return None.
433 pub fn get_bulb(&self, id: &String) -> Option<Bulb<'_>> {
434 let bulb = maliput_sys::api::rules::ffi::BulbGroup_GetBulb(self.bulb_group, id);
435 if bulb.is_null() {
436 return None;
437 }
438 Some(Bulb {
439 bulb: unsafe { bulb.as_ref().expect("Unable to get underlying bulb pointer") },
440 })
441 }
442
443 /// Returns the parent [TrafficLight] of the bulb group.
444 ///
445 /// # Returns
446 /// The parent [TrafficLight] of the bulb group.
447 pub fn traffic_light(&self) -> TrafficLight<'_> {
448 TrafficLight {
449 traffic_light: unsafe {
450 maliput_sys::api::rules::ffi::BulbGroup_traffic_light(self.bulb_group)
451 .as_ref()
452 .expect("Unable to get underlying traffic light pointer. The BulbGroup might not be registered to a TrafficLight.")
453 },
454 }
455 }
456}
457
458/// Uniquely identifies a bulb in the `Inertial` space. This consists of the
459/// concatenation of the bulb's ID, the ID of the bulb group that contains the
460/// bulb, and the the ID of the traffic light that contains the bulb group.
461///
462/// String representation of this ID is:
463/// "`traffic_light_id().string()`-`bulb_group_id.string()`-`bulb_id.string()`"
464pub struct UniqueBulbId {
465 unique_bulb_id: cxx::UniquePtr<maliput_sys::api::rules::ffi::UniqueBulbId>,
466}
467
468impl UniqueBulbId {
469 /// Get the traffic light id of the [UniqueBulbId].
470 ///
471 /// # Returns
472 /// The traffic light id of the [UniqueBulbId].
473 pub fn traffic_light_id(&self) -> String {
474 maliput_sys::api::rules::ffi::UniqueBulbId_traffic_light_id(&self.unique_bulb_id)
475 }
476
477 /// Get the bulb group id of the [UniqueBulbId].
478 ///
479 /// # Returns
480 /// The bulb group id of the [UniqueBulbId].
481 pub fn bulb_group_id(&self) -> String {
482 maliput_sys::api::rules::ffi::UniqueBulbId_bulb_group_id(&self.unique_bulb_id)
483 }
484
485 /// Get the bulb id of the [UniqueBulbId].
486 ///
487 /// # Returns
488 /// The bulb id of the [UniqueBulbId].
489 pub fn bulb_id(&self) -> String {
490 maliput_sys::api::rules::ffi::UniqueBulbId_bulb_id(&self.unique_bulb_id)
491 }
492
493 /// Get the string representation of the [UniqueBulbId].
494 ///
495 /// # Returns
496 /// The string representation of the [UniqueBulbId].
497 pub fn string(&self) -> String {
498 self.unique_bulb_id.string().to_string()
499 }
500}
501
502/// Uniquely identifies a bulb group in the `Inertial` space. This consists of
503/// the concatenation of the ID of the bulb group, and the ID of the traffic
504/// light that contains the bulb group.
505///
506/// String representation of this ID is:
507/// "`traffic_light_id().string()`-`bulb_group_id.string()`"
508pub struct UniqueBulbGroupId {
509 unique_bulb_group_id: cxx::UniquePtr<maliput_sys::api::rules::ffi::UniqueBulbGroupId>,
510}
511
512impl UniqueBulbGroupId {
513 /// Get the traffic light id of the [UniqueBulbGroupId].
514 ///
515 /// # Returns
516 /// The traffic light id of the [UniqueBulbGroupId].
517 pub fn traffic_light_id(&self) -> String {
518 maliput_sys::api::rules::ffi::UniqueBulbGroupId_traffic_light_id(&self.unique_bulb_group_id)
519 }
520
521 /// Get the bulb group id of the [UniqueBulbGroupId].
522 ///
523 /// # Returns
524 /// The bulb group id of the [UniqueBulbGroupId].
525 pub fn bulb_group_id(&self) -> String {
526 maliput_sys::api::rules::ffi::UniqueBulbGroupId_bulb_group_id(&self.unique_bulb_group_id)
527 }
528
529 /// Get the string representation of the [UniqueBulbGroupId].
530 ///
531 /// # Returns
532 /// The string representation of the [UniqueBulbGroupId].
533 pub fn string(&self) -> String {
534 self.unique_bulb_group_id.string().to_string()
535 }
536}
537/// Abstraction for holding the output of [RoadRulebook::rules()] and [RoadRulebook::find_rules()]
538/// methods.
539/// This struct contains a map of [DiscreteValueRule]s and [RangeValueRule]s.
540/// The keys of the map are the ids of the rules.
541/// The values of the map are the rules.
542pub struct QueryResults {
543 pub discrete_value_rules: std::collections::HashMap<String, DiscreteValueRule>,
544 pub range_value_rules: std::collections::HashMap<String, RangeValueRule>,
545}
546
547/// Interface for querying "rules of the road". This interface
548/// provides access to static information about a road network (i.e.,
549/// information determined prior to the beginning of a simulation). Some
550/// rule types may refer to additional dynamic information which will be
551/// provided by other interfaces.
552pub struct RoadRulebook<'a> {
553 pub(super) road_rulebook: &'a maliput_sys::api::rules::ffi::RoadRulebook,
554}
555
556impl<'a> RoadRulebook<'a> {
557 /// Returns the DiscreteValueRule with the specified `id`.
558 ///
559 /// # Arguments
560 /// * `rule_id` - The id of the rule.
561 ///
562 /// # Returns
563 /// The DiscreteValueRule with the given id or None if the id is not in the Rulebook.
564 pub fn get_discrete_value_rule(&self, rule_id: &String) -> Option<DiscreteValueRule> {
565 let discrete_value_rule =
566 maliput_sys::api::rules::ffi::RoadRulebook_GetDiscreteValueRule(self.road_rulebook, rule_id);
567 if discrete_value_rule.is_null() {
568 return None;
569 }
570 Some(DiscreteValueRule { discrete_value_rule })
571 }
572 /// Returns the RangeValueRule with the specified `id`.
573 ///
574 /// # Arguments
575 /// * `rule_id` - The id of the rule.
576 ///
577 /// # Returns
578 /// The RangeValueRule with the given id or None if the id is not in the Rulebook.
579 pub fn get_range_value_rule(&self, rule_id: &String) -> Option<RangeValueRule> {
580 let range_value_rule =
581 maliput_sys::api::rules::ffi::RoadRulebook_GetRangeValueRule(self.road_rulebook, rule_id);
582 if range_value_rule.is_null() {
583 return None;
584 }
585 Some(RangeValueRule { range_value_rule })
586 }
587
588 /// Returns all the rules in the road rulebook.
589 ///
590 /// # Returns
591 /// A [QueryResults] containing all the rules in the road rulebook.
592 pub fn rules(&self) -> QueryResults {
593 let query_results_cpp = maliput_sys::api::rules::ffi::RoadRulebook_Rules(self.road_rulebook);
594 let discrete_value_rules_id =
595 maliput_sys::api::rules::ffi::QueryResults_discrete_value_rules(&query_results_cpp);
596 let range_value_rules_id = maliput_sys::api::rules::ffi::QueryResults_range_value_rules(&query_results_cpp);
597 let mut dvr_map = std::collections::HashMap::new();
598 for rule_id in discrete_value_rules_id {
599 // It is okay to unwrap here since we are iterating valid IDs obtained above.
600 let rule = self.get_discrete_value_rule(&rule_id).unwrap();
601 dvr_map.insert(rule.id(), rule);
602 }
603 let mut rvr_map = std::collections::HashMap::new();
604 for rule_id in range_value_rules_id {
605 // It is okay to unwrap here since we are iterating valid IDs obtained above.
606 let rule = self.get_range_value_rule(&rule_id).unwrap();
607 rvr_map.insert(rule.id(), rule);
608 }
609 QueryResults {
610 discrete_value_rules: dvr_map,
611 range_value_rules: rvr_map,
612 }
613 }
614
615 /// Finds rules that apply to the given lane s ranges.
616 ///
617 /// # Arguments
618 /// * `ranges` - A vector of [super::LaneSRange]s to find rules for.
619 /// * `tolerance` - A tolerance value to use when finding rules.
620 ///
621 /// # Returns
622 /// A [QueryResults] containing the rules that apply to the given lane s ranges.
623 /// If no rules are found, an empty [QueryResults] is returned.
624 ///
625 /// # Errors
626 /// Returns a [MaliputError] if the underlying C++ function fails.
627 pub fn find_rules(&self, ranges: &Vec<super::LaneSRange>, tolerance: f64) -> Result<QueryResults, MaliputError> {
628 let mut ranges_cpp = Vec::new();
629 for range in ranges {
630 ranges_cpp.push(maliput_sys::api::rules::ffi::ConstLaneSRangeRef {
631 lane_s_range: &range.lane_s_range,
632 });
633 }
634 let query_results_cpp =
635 maliput_sys::api::rules::ffi::RoadRulebook_FindRules(self.road_rulebook, &ranges_cpp, tolerance)?;
636
637 let discrete_value_rules_id =
638 maliput_sys::api::rules::ffi::QueryResults_discrete_value_rules(&query_results_cpp);
639 let range_value_rules_id = maliput_sys::api::rules::ffi::QueryResults_range_value_rules(&query_results_cpp);
640 let mut dvr_map = std::collections::HashMap::new();
641 for rule_id in discrete_value_rules_id {
642 if let Some(rule) = self.get_discrete_value_rule(&rule_id) {
643 dvr_map.insert(rule.id(), rule);
644 }
645 }
646 let mut rvr_map = std::collections::HashMap::new();
647 for rule_id in range_value_rules_id {
648 if let Some(rule) = self.get_range_value_rule(&rule_id) {
649 rvr_map.insert(rule.id(), rule);
650 }
651 }
652 Ok(QueryResults {
653 discrete_value_rules: dvr_map,
654 range_value_rules: rvr_map,
655 })
656 }
657}
658
659/// # Rule
660///
661/// A Rule may have multiple states that affect agent behavior while it is
662/// driving through the rule's zone. The possible states of a Rule must be
663/// semantically coherent. The current state of a Rule is given by a
664/// [RuleStateProvider]. States can be:
665///
666/// - range based ([RangeValueRule]).
667/// - discrete ([DiscreteValueRule]).
668///
669/// # DiscreteValueRule
670///
671/// [DiscreteValue]s are defined by a string value.
672/// Semantics of this rule are based on _all_ possible values that this
673/// [DiscreteValueRule::type_id] could have (as specified by RuleRegistry::FindRuleByType()),
674/// not only the subset of values that a specific instance of this rule can
675/// be in.
676pub struct DiscreteValueRule {
677 discrete_value_rule: cxx::UniquePtr<maliput_sys::api::rules::ffi::DiscreteValueRule>,
678}
679
680impl DiscreteValueRule {
681 /// Returns the Id of the rule as a string.
682 ///
683 /// # Returns
684 /// The id of the rule.
685 pub fn id(&self) -> String {
686 maliput_sys::api::rules::ffi::DiscreteValueRule_id(&self.discrete_value_rule)
687 }
688 /// Returns the type of the rule as a string.
689 /// Example: "right-of-way-rule-type-id", "direction-usage-rule-type-id"
690 ///
691 /// # Returns
692 /// The type id of the rule.
693 pub fn type_id(&self) -> String {
694 maliput_sys::api::rules::ffi::DiscreteValueRule_type_id(&self.discrete_value_rule)
695 }
696 /// Returns a [crate::api::LaneSRoute] that represents the zone that the rule applies to.
697 ///
698 /// # Returns
699 /// A [crate::api::LaneSRoute] representing the zone of the rule.
700 pub fn zone(&self) -> crate::api::LaneSRoute {
701 let lane_s_route = maliput_sys::api::rules::ffi::DiscreteValueRule_zone(&self.discrete_value_rule);
702 crate::api::LaneSRoute { lane_s_route }
703 }
704 /// Returns the states of the rule.
705 ///
706 /// # Returns
707 /// A vector of [DiscreteValue]s representing the states of the rule.
708 /// If the rule has no states, an empty vector is returned.
709 pub fn states(&self) -> Vec<DiscreteValue> {
710 let states_cpp = &self.discrete_value_rule.states();
711 states_cpp
712 .into_iter()
713 .map(|dv| DiscreteValue {
714 rule_state: RuleStateBase {
715 severity: maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue_severity(dv),
716 related_rules: maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue_related_rules(dv),
717 related_unique_ids: maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue_related_unique_ids(
718 dv,
719 ),
720 },
721 value: maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue_value(dv),
722 })
723 .collect::<Vec<DiscreteValue>>()
724 }
725}
726
727impl std::fmt::Debug for DiscreteValueRule {
728 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
729 write!(
730 f,
731 "DiscreteValueRule {{ id: {}, type_id: {}, zone: {:?}, states: {:?} }}",
732 self.id(),
733 self.type_id(),
734 self.zone(),
735 self.states()
736 )
737 }
738}
739
740/// # Rule
741///
742/// A Rule may have multiple states that affect agent behavior while it is
743/// driving through the rule's zone. The possible states of a Rule must be
744/// semantically coherent. The current state of a Rule is given by a
745/// [RuleStateProvider]. States can be:
746///
747/// - range based ([RangeValueRule]).
748/// - discrete ([DiscreteValueRule]).
749///
750/// # RangeValueRule
751///
752/// [Range]s describe a numeric range based rule.
753/// Ranges are closed and continuous, defined by a minimum and maximum quantity.
754/// When only one extreme is formally defined, the other should take a
755/// semantically correct value. For example, if a speed limit only specifies a
756/// maximum value, the minimum value is typically zero.
757pub struct RangeValueRule {
758 range_value_rule: cxx::UniquePtr<maliput_sys::api::rules::ffi::RangeValueRule>,
759}
760
761impl RangeValueRule {
762 /// Returns the Id of the rule as a string.
763 ///
764 /// # Returns
765 /// The id of the rule.
766 pub fn id(&self) -> String {
767 maliput_sys::api::rules::ffi::RangeValueRule_id(&self.range_value_rule)
768 }
769 /// Returns the type of the rule as a string.
770 /// Example: "right-of-way-rule-type-id", "direction-usage-rule-type-id"
771 ///
772 /// # Returns
773 /// The type id of the rule.
774 pub fn type_id(&self) -> String {
775 maliput_sys::api::rules::ffi::RangeValueRule_type_id(&self.range_value_rule)
776 }
777 /// Returns a [crate::api::LaneSRoute] that represents the zone that the rule applies to.
778 ///
779 /// # Returns
780 /// A [crate::api::LaneSRoute] representing the zone of the rule.
781 pub fn zone(&self) -> crate::api::LaneSRoute {
782 let lane_s_route = maliput_sys::api::rules::ffi::RangeValueRule_zone(&self.range_value_rule);
783 crate::api::LaneSRoute { lane_s_route }
784 }
785 /// Returns the states of the rule.
786 ///
787 /// # Returns
788 /// A vector of [Range]s representing the states of the rule.
789 /// If the rule has no states, an empty vector is returned.
790 pub fn states(&self) -> Vec<Range> {
791 let states_cpp = &self.range_value_rule.states();
792 states_cpp
793 .into_iter()
794 .map(|r| Range {
795 rule_state: RuleStateBase {
796 severity: maliput_sys::api::rules::ffi::RangeValueRuleRange_severity(r),
797 related_rules: maliput_sys::api::rules::ffi::RangeValueRuleRange_related_rules(r),
798 related_unique_ids: maliput_sys::api::rules::ffi::RangeValueRuleRange_related_unique_ids(r),
799 },
800 description: maliput_sys::api::rules::ffi::RangeValueRuleRange_description(r),
801 min: maliput_sys::api::rules::ffi::RangeValueRuleRange_min(r),
802 max: maliput_sys::api::rules::ffi::RangeValueRuleRange_max(r),
803 })
804 .collect::<Vec<Range>>()
805 }
806}
807
808/// Defines a Rule Type.
809///
810/// # RuleType
811///
812/// [RuleType]s provide a way of obtaining a rule type's string defined in
813/// maliput's backend. Since new rule types can be created in a custom manner,
814/// [RuleType] only holds the most common types which are already defined in
815/// the backend.
816#[derive(Display, IntoStaticStr)]
817pub enum RuleType {
818 #[strum(serialize = "Direction-Usage Rule Type")]
819 DirectionUsage,
820 #[strum(serialize = "Right-Of-Way Rule Type")]
821 RightOfWay,
822 #[strum(serialize = "Vehicle-Stop-In-Zone-Behavior Rule Type")]
823 VehicleStopInZoneBehavior,
824 #[strum(serialize = "Speed-Limit Rule Type")]
825 SpeedLimit,
826}
827
828impl RuleType {
829 /// Gets the Rule ID for the [RuleType] and `lane_id`.
830 ///
831 /// # Arguments
832 /// - `lane_id` - The lane ID to get the rule ID from.
833 ///
834 /// # Returns
835 /// A rule ID formatted the way the backend defines it.
836 pub fn get_rule_id(&self, lane_id: &str) -> String {
837 // We rely on maliput_malidrive which define the rule id as:
838 // "<rule_type>/<lane_id>"
839 self.to_string() + "/" + lane_id
840 }
841}
842
843/// Defines a base state for a rule.
844///
845/// # RuleStateBase
846///
847/// - `severity` - The severity of the rule state.
848/// - `related_rules` - A map of related rules. The key is the group name and the value is a vector of rule ids.
849/// - `related_unique_ids` - A map of related unique ids. The key is the group name and the value is a vector of unique ids.
850///
851/// See [DiscreteValueRule] and [RangeValueRule] for more information.
852pub struct RuleStateBase {
853 /// Severity of the rule's state. A non-negative quantity that specifies the
854 /// level of enforcement. The smaller it is, the more strictly the rule is
855 /// enforced. Each rule type can define its own set of severity level
856 /// semantics.
857 severity: i32,
858 related_rules: cxx::UniquePtr<cxx::CxxVector<maliput_sys::api::rules::ffi::RelatedRule>>,
859 related_unique_ids: cxx::UniquePtr<cxx::CxxVector<maliput_sys::api::rules::ffi::RelatedUniqueId>>,
860}
861
862/// A trait representing a possible state of a `Rule`.
863///
864/// A `Rule` can have multiple states that affect agent behavior. This trait
865/// provides a common interface for accessing the properties shared by all
866/// rule states, such as severity and related rules.
867///
868/// This trait is implemented by specific state types like [`DiscreteValue`]
869/// and [`Range`].
870///
871/// # Implementors
872///
873/// When implementing this trait, you must provide an implementation for the
874/// [`get_rule_state()`] method, which gives access to the underlying
875/// [`RuleStateBase`] data. The other methods have default implementations.
876pub trait RuleState {
877 /// Gets the underlying [`RuleStateBase`] that contains common state properties.
878 ///
879 /// # Returns
880 /// A reference to the [`RuleStateBase`] that contains the severity, related rules,
881 /// and related unique ids for the rule state.
882 fn get_rule_state(&self) -> &RuleStateBase;
883
884 /// Returns the severity of the rule state.
885 ///
886 /// # Returns
887 /// An `i32` representing the severity of the rule state.
888 /// The severity is a numeric value that indicates the importance or urgency of the rule. The lower the value, the more strictly the rule is enforced.
889 fn severity(&self) -> i32 {
890 self.get_rule_state().severity
891 }
892
893 /// Returns a map of related rules ids. The key is the group name and the value is a vector of rule ids.
894 ///
895 /// # Returns
896 /// A map of related rules where the key is the group name and the value is a vector of rule ids.
897 fn related_rules(&self) -> std::collections::HashMap<&String, &Vec<String>> {
898 self.get_rule_state()
899 .related_rules
900 .iter()
901 .map(|rr| (&rr.group_name, &rr.rule_ids))
902 .collect::<std::collections::HashMap<&String, &Vec<String>>>()
903 }
904 /// Returns a map of related unique ids. The key is the group name and the value is a vector of unique ids.
905 ///
906 /// # Returns
907 /// A map of related unique ids where the key is the group name and the value is a vector of unique ids.
908 fn related_unique_ids(&self) -> std::collections::HashMap<&String, &Vec<String>> {
909 self.get_rule_state()
910 .related_unique_ids
911 .iter()
912 .map(|rui| (&rui.group_name, &rui.unique_ids))
913 .collect::<std::collections::HashMap<&String, &Vec<String>>>()
914 }
915}
916
917/// Defines a discrete value for a [DiscreteValueRule].
918/// It extends the [RuleStateBase] with the value of the discrete value.
919pub struct DiscreteValue {
920 rule_state: RuleStateBase,
921 value: String,
922}
923
924impl RuleState for DiscreteValue {
925 fn get_rule_state(&self) -> &RuleStateBase {
926 &self.rule_state
927 }
928}
929
930impl DiscreteValue {
931 /// Returns the value of the discrete value.
932 pub fn value(&self) -> &String {
933 &self.value
934 }
935}
936
937impl std::fmt::Debug for DiscreteValue {
938 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
939 write!(
940 f,
941 "DiscreteValue {{ value: {}, severity: {}, related_rules: {:?}, related_unique_ids: {:?} }}",
942 self.value(),
943 self.severity(),
944 self.related_rules(),
945 self.related_unique_ids()
946 )
947 }
948}
949
950/// Defines a range value for a [RangeValueRule].
951/// It extends the [RuleStateBase] with the description, and min and max values of the range.
952pub struct Range {
953 rule_state: RuleStateBase,
954 description: String,
955 min: f64,
956 max: f64,
957}
958
959impl RuleState for Range {
960 fn get_rule_state(&self) -> &RuleStateBase {
961 &self.rule_state
962 }
963}
964
965impl Range {
966 /// Returns the description of the range value.
967 pub fn description(&self) -> &String {
968 &self.description
969 }
970 /// Returns the minimum value of the range.
971 pub fn min(&self) -> f64 {
972 self.min
973 }
974 /// Returns the maximum value of the range.
975 pub fn max(&self) -> f64 {
976 self.max
977 }
978}
979
980/// Defines a phase in a traffic rule system.
981///
982/// A phase represents a specific state or configuration of traffic signals
983/// and semantic rules within a traffic control system. Each phase has a unique
984/// identifier and may include various traffic signal states and rule configurations
985/// that dictate how traffic should behave during that phase.
986pub struct Phase {
987 phase: cxx::UniquePtr<maliput_sys::api::rules::ffi::Phase>,
988}
989
990impl Phase {
991 /// Gets the id of the [Phase].
992 ///
993 /// # Returns
994 /// The id of the [Phase].
995 pub fn id(&self) -> String {
996 maliput_sys::api::rules::ffi::Phase_id(&self.phase)
997 }
998}
999
1000/// Defines a ring of phases in a traffic rule system.
1001///
1002/// A phase ring represents a sequence of phases that a traffic control system
1003/// cycles through.
1004pub struct PhaseRing {
1005 phase_ring: cxx::UniquePtr<maliput_sys::api::rules::ffi::PhaseRing>,
1006}
1007
1008impl PhaseRing {
1009 /// Gets the id of the [PhaseRing].
1010 ///
1011 /// # Returns
1012 /// The id of the [PhaseRing].
1013 pub fn id(&self) -> String {
1014 maliput_sys::api::rules::ffi::PhaseRing_id(&self.phase_ring)
1015 }
1016
1017 /// Gets a [Phase] by its id
1018 ///
1019 /// # Arguments
1020 /// * `id` - The id of the [Phase].
1021 /// # Returns
1022 /// The [Phase] with the given id.
1023 /// If no [Phase] is found with the given id, return None.
1024 pub fn get_phase(&self, id: &String) -> Option<Phase> {
1025 let phase = maliput_sys::api::rules::ffi::PhaseRing_GetPhase(&self.phase_ring, id);
1026 if phase.is_null() {
1027 return None;
1028 }
1029 Some(Phase { phase })
1030 }
1031
1032 /// Returns the ids of all Phases in the PhaseRing.
1033 ///
1034 /// # Returns
1035 /// A vector of strings representing the ids of all Phases in the PhaseRing.
1036 pub fn phases(&self) -> Vec<String> {
1037 maliput_sys::api::rules::ffi::PhaseRing_phases_ids(&self.phase_ring)
1038 }
1039}
1040
1041/// Defines a book of phase rings in a traffic rule system.
1042pub struct PhaseRingBook<'a> {
1043 pub(super) phase_ring_book: &'a maliput_sys::api::rules::ffi::PhaseRingBook,
1044}
1045
1046impl<'a> PhaseRingBook<'a> {
1047 /// Returns the ids of all PhaseRings in the PhaseRingBook.
1048 ///
1049 /// # Returns
1050 /// A vector of strings representing the ids of all PhaseRings in the PhaseRingBook.
1051 pub fn get_phase_rings_ids(&self) -> Vec<String> {
1052 maliput_sys::api::rules::ffi::PhaseRingBook_GetPhaseRingsId(self.phase_ring_book)
1053 }
1054
1055 /// Returns the PhaseRing with the specified `id`.
1056 ///
1057 /// # Arguments
1058 /// * `phase_ring_id` - The id of the phase ring.
1059 ///
1060 /// # Returns
1061 /// The PhaseRing with the given id or None if the id is not in the PhaseRingBook.
1062 pub fn get_phase_ring(&self, phase_ring_id: &String) -> Option<PhaseRing> {
1063 let phase_ring = maliput_sys::api::rules::ffi::PhaseRingBook_GetPhaseRing(self.phase_ring_book, phase_ring_id);
1064 if phase_ring.is_null() {
1065 return None;
1066 }
1067 Some(PhaseRing { phase_ring })
1068 }
1069}