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 std::collections::HashMap;
32
33use crate::{api::RoadPosition, common::MaliputError};
34use strum_macros::{Display, IntoStaticStr};
35
36/// Interface for accessing the [TrafficLight] in the [super::RoadNetwork]
37pub struct TrafficLightBook<'a> {
38 pub(super) traffic_light_book: &'a maliput_sys::api::rules::ffi::TrafficLightBook,
39}
40
41impl<'a> TrafficLightBook<'a> {
42 /// Gets all the [TrafficLight]s in the [TrafficLightBook]
43 ///
44 /// # Returns
45 /// A vector of [TrafficLight]s
46 pub fn traffic_lights(&self) -> Vec<TrafficLight<'_>> {
47 let traffic_lights_cpp = maliput_sys::api::rules::ffi::TrafficLightBook_TrafficLights(self.traffic_light_book);
48 traffic_lights_cpp
49 .into_iter()
50 .map(|tl| TrafficLight {
51 traffic_light: unsafe { tl.traffic_light.as_ref().expect("") },
52 })
53 .collect::<Vec<TrafficLight>>()
54 }
55
56 /// Gets a [TrafficLight] by its id.
57 ///
58 /// # Arguments
59 /// * `id` - The id of the [TrafficLight].
60 ///
61 /// # Returns
62 /// The [TrafficLight] with the given id.
63 /// If no [TrafficLight] is found with the given id, return None.
64 pub fn get_traffic_light(&self, id: &String) -> Option<TrafficLight<'_>> {
65 let traffic_light = maliput_sys::api::rules::ffi::TrafficLightBook_GetTrafficLight(self.traffic_light_book, id);
66 if traffic_light.is_null() {
67 return None;
68 }
69 Some(TrafficLight {
70 traffic_light: unsafe {
71 traffic_light
72 .as_ref()
73 .expect("Unable to get underlying traffic light pointer")
74 },
75 })
76 }
77}
78
79/// Models a traffic light. A traffic light is a physical signaling device
80/// typically located at road intersections. It contains one or more groups of
81/// light bulbs with varying colors and shapes. The lighting patterns of the
82/// bulbs signify right-of-way rule information to the agents navigating the
83/// intersection (e.g., vehicles, bicyclists, pedestrians, etc.). Typically, an
84/// intersection will be managed by multiple traffic lights.
85///
86/// Note that traffic lights are physical manifestations of underlying
87/// right-of-way rules and thus naturally have lower signal-to-noise ratio
88/// relative to the underlying rules. Thus, oracular agents should directly use
89/// the underlying right-of-way rules instead of traffic lights when navigating
90/// intersections. TrafficLight exists for testing autonomous vehicles that do
91/// not have access to right-of-way rules.
92pub struct TrafficLight<'a> {
93 pub traffic_light: &'a maliput_sys::api::rules::ffi::TrafficLight,
94}
95
96impl<'a> TrafficLight<'a> {
97 /// Get the id of the [TrafficLight].
98 ///
99 /// # Returns
100 /// The id of the [TrafficLight].
101 pub fn id(&self) -> String {
102 maliput_sys::api::rules::ffi::TrafficLight_id(self.traffic_light)
103 }
104
105 /// Get the position of the [TrafficLight] in the road network.
106 ///
107 /// # Returns
108 /// An [super::InertialPosition] representing the position of the [TrafficLight] in the road network.
109 pub fn position_road_network(&self) -> super::InertialPosition {
110 let inertial_position = maliput_sys::api::rules::ffi::TrafficLight_position_road_network(self.traffic_light);
111 super::InertialPosition { ip: inertial_position }
112 }
113
114 /// Get the orientation of the [TrafficLight] in the road network.
115 ///
116 /// # Returns
117 /// An [super::Rotation] representing the orientation of the [TrafficLight] in the road network.
118 pub fn orientation_road_network(&self) -> super::Rotation {
119 let rotation = maliput_sys::api::rules::ffi::TrafficLight_orientation_road_network(self.traffic_light);
120 super::Rotation { r: rotation }
121 }
122
123 /// Get the bulb groups of the [TrafficLight].
124 ///
125 /// # Returns
126 /// A vector of [BulbGroup]s in the [TrafficLight].
127 /// If the [TrafficLight] has no bulb groups, return an empty vector.
128 pub fn bulb_groups(&self) -> Vec<BulbGroup<'_>> {
129 let bulb_groups_cpp = maliput_sys::api::rules::ffi::TrafficLight_bulb_groups(self.traffic_light);
130 bulb_groups_cpp
131 .into_iter()
132 .map(|bg| BulbGroup {
133 bulb_group: unsafe { bg.bulb_group.as_ref().expect("") },
134 })
135 .collect::<Vec<BulbGroup>>()
136 }
137
138 /// Get a [BulbGroup] by its id.
139 ///
140 /// # Arguments
141 /// * `id` - The id of the [BulbGroup].
142 ///
143 /// # Returns
144 /// The [BulbGroup] with the given id.
145 /// If no [BulbGroup] is found with the given id, return None.
146 pub fn get_bulb_group(&self, id: &String) -> Option<BulbGroup<'_>> {
147 let bulb_group = maliput_sys::api::rules::ffi::TrafficLight_GetBulbGroup(self.traffic_light, id);
148 if bulb_group.is_null() {
149 return None;
150 }
151 Some(BulbGroup {
152 bulb_group: unsafe {
153 bulb_group
154 .as_ref()
155 .expect("Unable to get underlying bulb group pointer")
156 },
157 })
158 }
159}
160
161#[derive(Debug, Copy, Clone, PartialEq, Eq)]
162/// Defines the possible bulb colors.
163pub enum BulbColor {
164 Red,
165 Yellow,
166 Green,
167}
168
169#[derive(Debug, Copy, Clone, PartialEq, Eq)]
170/// Defines the possible bulb types.
171pub enum BulbType {
172 Round,
173 Arrow,
174}
175
176#[derive(Debug, Copy, Clone, PartialEq, Eq)]
177/// Defines the possible bulb types.
178pub enum BulbState {
179 Off,
180 On,
181 Blinking,
182}
183
184/// Models a bulb within a bulb group.
185pub struct Bulb<'a> {
186 pub bulb: &'a maliput_sys::api::rules::ffi::Bulb,
187}
188
189impl Bulb<'_> {
190 /// Returns this Bulb instance's unique identifier.
191 ///
192 /// # Returns
193 /// A [UniqueBulbId] representing the unique identifier of the [Bulb].
194 pub fn unique_id(&self) -> UniqueBulbId {
195 UniqueBulbId {
196 unique_bulb_id: maliput_sys::api::rules::ffi::Bulb_unique_id(self.bulb),
197 }
198 }
199
200 /// Get the id of the [Bulb].
201 ///
202 /// # Returns
203 /// The id of the [Bulb].
204 pub fn id(&self) -> String {
205 maliput_sys::api::rules::ffi::Bulb_id(self.bulb)
206 }
207
208 /// Get the color of the [Bulb].
209 ///
210 /// # Returns
211 /// The [BulbColor].
212 pub fn color(&self) -> BulbColor {
213 let color = self.bulb.color();
214 match *color {
215 maliput_sys::api::rules::ffi::BulbColor::kRed => BulbColor::Red,
216 maliput_sys::api::rules::ffi::BulbColor::kYellow => BulbColor::Yellow,
217 maliput_sys::api::rules::ffi::BulbColor::kGreen => BulbColor::Green,
218 _ => panic!("Invalid bulb color"),
219 }
220 }
221
222 /// Get the type of the [Bulb].
223 ///
224 /// # Returns
225 /// The [BulbType].
226 pub fn bulb_type(&self) -> BulbType {
227 let bulb_type = maliput_sys::api::rules::ffi::Bulb_type(self.bulb);
228 match *bulb_type {
229 maliput_sys::api::rules::ffi::BulbType::kRound => BulbType::Round,
230 maliput_sys::api::rules::ffi::BulbType::kArrow => BulbType::Arrow,
231 _ => panic!("Invalid bulb type"),
232 }
233 }
234
235 /// Get the position of the [Bulb] in the bulb group.
236 ///
237 /// # Returns
238 /// An [super::InertialPosition] representing the position of the [Bulb] in the bulb group.
239 pub fn position_bulb_group(&self) -> super::InertialPosition {
240 let inertial_position = maliput_sys::api::rules::ffi::Bulb_position_bulb_group(self.bulb);
241 super::InertialPosition { ip: inertial_position }
242 }
243
244 /// Get the orientation of the [Bulb] in the bulb group.
245 ///
246 /// # Returns
247 /// An [super::Rotation] representing the orientation of the [Bulb] in the bulb group.
248 pub fn orientation_bulb_group(&self) -> super::Rotation {
249 let rotation = maliput_sys::api::rules::ffi::Bulb_orientation_bulb_group(self.bulb);
250 super::Rotation { r: rotation }
251 }
252
253 /// Returns the arrow's orientation. Only applicable if [Bulb::bulb_type] returns [BulbType::Arrow].
254 ///
255 /// # Returns
256 /// An `Option<f64>` representing the orientation of the arrow in radians.
257 pub fn arrow_orientation_rad(&self) -> Option<f64> {
258 let arrow_orientation = maliput_sys::api::rules::ffi::Bulb_arrow_orientation_rad(self.bulb);
259 if arrow_orientation.is_null() {
260 return None;
261 }
262 Some(arrow_orientation.value)
263 }
264
265 /// Gets the possible states of the [Bulb].
266 ///
267 /// # Returns
268 /// A vector of [BulbState]s representing the possible states of the [Bulb].
269 pub fn states(&self) -> Vec<BulbState> {
270 let states_cpp = maliput_sys::api::rules::ffi::Bulb_states(self.bulb);
271 states_cpp
272 .into_iter()
273 .map(Bulb::_from_cpp_state_to_rust_state)
274 .collect::<Vec<BulbState>>()
275 }
276
277 /// Gets the default state of the [Bulb].
278 ///
279 /// # Returns
280 /// A [BulbState] representing the default state of the [Bulb].
281 pub fn get_default_state(&self) -> BulbState {
282 let default_state = self.bulb.GetDefaultState();
283 Bulb::_from_cpp_state_to_rust_state(&default_state)
284 }
285
286 /// Check if the given state is possible valid for the [Bulb].
287 ///
288 /// # Arguments
289 /// * `state` - The [BulbState] to check.
290 ///
291 /// # Returns
292 /// A boolean indicating whether the given state is valid for the [Bulb].
293 pub fn is_valid_state(&self, state: &BulbState) -> bool {
294 self.bulb.IsValidState(&Bulb::_from_rust_state_to_cpp_state(state))
295 }
296
297 /// Returns the bounding box of the bulb.
298 ///
299 /// # Returns
300 /// A tuple containing the minimum and maximum points of the bounding box.
301 pub fn bounding_box(&self) -> (crate::math::Vector3, crate::math::Vector3) {
302 let min = maliput_sys::api::rules::ffi::Bulb_bounding_box_min(self.bulb);
303 let max = maliput_sys::api::rules::ffi::Bulb_bounding_box_max(self.bulb);
304 (crate::math::Vector3 { v: min }, crate::math::Vector3 { v: max })
305 }
306
307 /// Returns the parent [BulbGroup] of the bulb.
308 ///
309 /// # Returns
310 /// The parent [BulbGroup] of the bulb.
311 /// If the bulb is not part of any group, return None.
312 pub fn bulb_group(&self) -> BulbGroup<'_> {
313 BulbGroup {
314 bulb_group: unsafe {
315 maliput_sys::api::rules::ffi::Bulb_bulb_group(self.bulb)
316 .as_ref()
317 .expect("Unable to get underlying bulb group pointer. The Bulb might not be part of any BulbGroup.")
318 },
319 }
320 }
321
322 /// Convert from the C++ BulbState to the Rust BulbState
323 /// It is expected to be used only internally.
324 ///
325 /// # Arguments
326 /// * `cpp_bulb_state` - The C++ BulbState
327 ///
328 /// # Returns
329 /// The Rust BulbState
330 ///
331 /// # Panics
332 /// If the C++ BulbState is invalid.
333 fn _from_cpp_state_to_rust_state(cpp_bulb_state: &maliput_sys::api::rules::ffi::BulbState) -> BulbState {
334 match *cpp_bulb_state {
335 maliput_sys::api::rules::ffi::BulbState::kOff => BulbState::Off,
336 maliput_sys::api::rules::ffi::BulbState::kOn => BulbState::On,
337 maliput_sys::api::rules::ffi::BulbState::kBlinking => BulbState::Blinking,
338 _ => panic!("Invalid bulb state"),
339 }
340 }
341
342 /// Convert from the Rust BulbState to the C++ BulbState
343 /// It is expected to be used only internally.
344 ///
345 /// # Arguments
346 /// * `rust_bulb_state` - The Rust BulbState
347 ///
348 /// # Returns
349 /// The C++ BulbState
350 fn _from_rust_state_to_cpp_state(rust_bulb_state: &BulbState) -> maliput_sys::api::rules::ffi::BulbState {
351 match rust_bulb_state {
352 BulbState::Off => maliput_sys::api::rules::ffi::BulbState::kOff,
353 BulbState::On => maliput_sys::api::rules::ffi::BulbState::kOn,
354 BulbState::Blinking => maliput_sys::api::rules::ffi::BulbState::kBlinking,
355 }
356 }
357}
358
359/// Models a group of bulbs within a traffic light. All of the bulbs within a
360/// group should share the same approximate orientation. However, this is not
361/// programmatically enforced.
362/// About the bulb group pose:
363/// - The position of the bulb group is defined as the linear offset of this bulb group's frame
364/// relative to the frame of the traffic light that contains it. The origin of
365/// this bulb group's frame should approximate the bulb group's CoM.
366/// - The orientation of the bulb group is defined as the rotational offset of this bulb
367/// group's frame relative to the frame of the traffic light that contains it.
368/// The +Z axis should align with the bulb group's "up" direction, and the +X
369/// axis should point in the direction that the bulb group is facing.
370/// Following a right-handed coordinate frame, the +Y axis should point left
371/// when facing the +X direction.
372pub struct BulbGroup<'a> {
373 pub bulb_group: &'a maliput_sys::api::rules::ffi::BulbGroup,
374}
375
376impl BulbGroup<'_> {
377 /// Returns this BulbGroup instance's unique identifier.
378 ///
379 /// # Returns
380 /// A [UniqueBulbGroupId] representing the unique identifier of the [BulbGroup].
381 pub fn unique_id(&self) -> UniqueBulbGroupId {
382 UniqueBulbGroupId {
383 unique_bulb_group_id: maliput_sys::api::rules::ffi::BulbGroup_unique_id(self.bulb_group),
384 }
385 }
386
387 /// Gets the id of the [BulbGroup].
388 ///
389 /// # Returns
390 /// The id of the [BulbGroup].
391 pub fn id(&self) -> String {
392 maliput_sys::api::rules::ffi::BulbGroup_id(self.bulb_group)
393 }
394
395 /// Gets the position of the [BulbGroup] in the traffic light.
396 ///
397 /// # Returns
398 /// An [super::InertialPosition] representing the position of the [BulbGroup] in the traffic light.
399 pub fn position_traffic_light(&self) -> super::InertialPosition {
400 let inertial_position = maliput_sys::api::rules::ffi::BulbGroup_position_traffic_light(self.bulb_group);
401 super::InertialPosition { ip: inertial_position }
402 }
403
404 /// Gets the orientation of the [BulbGroup] in the traffic light.
405 ///
406 /// # Returns
407 /// An [super::Rotation] representing the orientation of the [BulbGroup] in the traffic light.
408 pub fn orientation_traffic_light(&self) -> super::Rotation {
409 let rotation = maliput_sys::api::rules::ffi::BulbGroup_orientation_traffic_light(self.bulb_group);
410 super::Rotation { r: rotation }
411 }
412
413 /// Returns the bulbs in the bulb group.
414 ///
415 /// # Returns
416 /// A vector of [Bulb]s in the bulb group.
417 pub fn bulbs(&self) -> Vec<Bulb<'_>> {
418 let bulbs_cpp = maliput_sys::api::rules::ffi::BulbGroup_bulbs(self.bulb_group);
419 bulbs_cpp
420 .into_iter()
421 .map(|b| Bulb {
422 bulb: unsafe { b.bulb.as_ref().expect("") },
423 })
424 .collect::<Vec<Bulb>>()
425 }
426
427 /// Gets a [Bulb] by its id
428 ///
429 /// # Arguments
430 /// * `id` - The id of the [Bulb].
431 ///
432 /// # Returns
433 /// The [Bulb] with the given id.
434 /// If no [Bulb] is found with the given id, return None.
435 pub fn get_bulb(&self, id: &String) -> Option<Bulb<'_>> {
436 let bulb = maliput_sys::api::rules::ffi::BulbGroup_GetBulb(self.bulb_group, id);
437 if bulb.is_null() {
438 return None;
439 }
440 Some(Bulb {
441 bulb: unsafe { bulb.as_ref().expect("Unable to get underlying bulb pointer") },
442 })
443 }
444
445 /// Returns the parent [TrafficLight] of the bulb group.
446 ///
447 /// # Returns
448 /// The parent [TrafficLight] of the bulb group.
449 pub fn traffic_light(&self) -> TrafficLight<'_> {
450 TrafficLight {
451 traffic_light: unsafe {
452 maliput_sys::api::rules::ffi::BulbGroup_traffic_light(self.bulb_group)
453 .as_ref()
454 .expect("Unable to get underlying traffic light pointer. The BulbGroup might not be registered to a TrafficLight.")
455 },
456 }
457 }
458}
459
460/// Uniquely identifies a bulb in the `Inertial` space. This consists of the
461/// concatenation of the bulb's ID, the ID of the bulb group that contains the
462/// bulb, and the the ID of the traffic light that contains the bulb group.
463///
464/// String representation of this ID is:
465/// "`traffic_light_id().string()`-`bulb_group_id.string()`-`bulb_id.string()`"
466pub struct UniqueBulbId {
467 pub(crate) unique_bulb_id: cxx::UniquePtr<maliput_sys::api::rules::ffi::UniqueBulbId>,
468}
469
470impl UniqueBulbId {
471 /// Get the traffic light id of the [UniqueBulbId].
472 ///
473 /// # Returns
474 /// The traffic light id of the [UniqueBulbId].
475 pub fn traffic_light_id(&self) -> String {
476 maliput_sys::api::rules::ffi::UniqueBulbId_traffic_light_id(&self.unique_bulb_id)
477 }
478
479 /// Get the bulb group id of the [UniqueBulbId].
480 ///
481 /// # Returns
482 /// The bulb group id of the [UniqueBulbId].
483 pub fn bulb_group_id(&self) -> String {
484 maliput_sys::api::rules::ffi::UniqueBulbId_bulb_group_id(&self.unique_bulb_id)
485 }
486
487 /// Get the bulb id of the [UniqueBulbId].
488 ///
489 /// # Returns
490 /// The bulb id of the [UniqueBulbId].
491 pub fn bulb_id(&self) -> String {
492 maliput_sys::api::rules::ffi::UniqueBulbId_bulb_id(&self.unique_bulb_id)
493 }
494
495 /// Get the string representation of the [UniqueBulbId].
496 ///
497 /// # Returns
498 /// The string representation of the [UniqueBulbId].
499 pub fn string(&self) -> String {
500 self.unique_bulb_id.string().to_string()
501 }
502}
503
504/// Uniquely identifies a bulb group in the `Inertial` space. This consists of
505/// the concatenation of the ID of the bulb group, and the ID of the traffic
506/// light that contains the bulb group.
507///
508/// String representation of this ID is:
509/// "`traffic_light_id().string()`-`bulb_group_id.string()`"
510pub struct UniqueBulbGroupId {
511 unique_bulb_group_id: cxx::UniquePtr<maliput_sys::api::rules::ffi::UniqueBulbGroupId>,
512}
513
514impl UniqueBulbGroupId {
515 /// Get the traffic light id of the [UniqueBulbGroupId].
516 ///
517 /// # Returns
518 /// The traffic light id of the [UniqueBulbGroupId].
519 pub fn traffic_light_id(&self) -> String {
520 maliput_sys::api::rules::ffi::UniqueBulbGroupId_traffic_light_id(&self.unique_bulb_group_id)
521 }
522
523 /// Get the bulb group id of the [UniqueBulbGroupId].
524 ///
525 /// # Returns
526 /// The bulb group id of the [UniqueBulbGroupId].
527 pub fn bulb_group_id(&self) -> String {
528 maliput_sys::api::rules::ffi::UniqueBulbGroupId_bulb_group_id(&self.unique_bulb_group_id)
529 }
530
531 /// Get the string representation of the [UniqueBulbGroupId].
532 ///
533 /// # Returns
534 /// The string representation of the [UniqueBulbGroupId].
535 pub fn string(&self) -> String {
536 self.unique_bulb_group_id.string().to_string()
537 }
538}
539
540/// Interface for querying types of rules. It includes both Discrete and Range value rules. It
541/// provides a registry of the various rule types.
542pub struct RuleRegistry<'a> {
543 pub(super) rule_registry: &'a maliput_sys::api::rules::ffi::RuleRegistry,
544}
545
546/// Represents the rule values the [RuleRegistry] can contain by their Discrete or Range type.
547pub enum RuleValuesByType {
548 DiscreteValues(Vec<DiscreteValue>),
549 Ranges(Vec<Range>),
550}
551
552impl<'a> RuleRegistry<'a> {
553 /// Returns all [DiscreteValue] rule type IDs.
554 ///
555 /// # Returns
556 /// A vector of [String]s representing rule type IDs that correspond to different
557 /// [DiscreteValue]s in the [RuleRegistry].
558 pub fn get_discrete_value_rule_types(&self) -> Vec<String> {
559 let discrete_value_types =
560 maliput_sys::api::rules::ffi::RuleRegistry_DiscreteValueRuleTypes(self.rule_registry);
561 let discrete_value_types = discrete_value_types
562 .as_ref()
563 .expect("Unable to get underlying discrete value rule types pointer.");
564 discrete_value_types.iter().map(|dvt| dvt.type_id.clone()).collect()
565 }
566
567 /// Returns all [DiscreteValue]s corresponding to the specified `rule_type_id`.
568 ///
569 /// This methods works in tandem with [RuleRegistry::get_discrete_value_rule_types].
570 ///
571 /// # Arguments
572 /// * `rule_type_id` - The id of the rule type.
573 ///
574 /// # Returns
575 /// A vector of [DiscreteValue]s or [None] if the `rule_type_id` doesn't match any type id in
576 /// the [RuleRegistry].
577 pub fn discrete_values_by_type(&self, rule_type_id: String) -> Option<Vec<DiscreteValue>> {
578 let discrete_value_types =
579 maliput_sys::api::rules::ffi::RuleRegistry_DiscreteValueRuleTypes(self.rule_registry);
580 let discrete_value_types = discrete_value_types
581 .as_ref()
582 .expect("Unable to get underlying discrete value rule types pointer.");
583 discrete_value_types
584 .iter()
585 .find(|dvt| dvt.type_id == rule_type_id)
586 .map(|dvt| discrete_values_from_cxx(&dvt.values))
587 }
588
589 /// Returns all [Range] rule type IDs.
590 ///
591 /// # Returns
592 /// A vector of [String]s representing rule type IDs that correspond to different [Range]s in
593 /// the [RuleRegistry].
594 pub fn get_range_rule_types(&self) -> Vec<String> {
595 let range_value_types = maliput_sys::api::rules::ffi::RuleRegistry_RangeValueRuleTypes(self.rule_registry);
596 let range_value_types = range_value_types
597 .as_ref()
598 .expect("Unable to get underlying range rule types pointer.");
599 range_value_types.iter().map(|rvt| rvt.type_id.clone()).collect()
600 }
601
602 /// Returns all [Range]s corresponding to the specified `rule_type_id`.
603 ///
604 /// This methods works in tandem with [RuleRegistry::get_range_rule_types].
605 ///
606 /// # Arguments
607 /// * `rule_type_id` - The id of the rule type.
608 ///
609 /// # Returns
610 /// A vector of [Range]s or [None] if the `rule_type_id` doesn't match any type id in the
611 /// [RuleRegistry].
612 pub fn range_values_by_type(&self, rule_type_id: String) -> Option<Vec<Range>> {
613 let range_value_types = maliput_sys::api::rules::ffi::RuleRegistry_RangeValueRuleTypes(self.rule_registry);
614 let range_value_types = range_value_types
615 .as_ref()
616 .expect("Unable to get underlying range rule types pointer.");
617 range_value_types
618 .iter()
619 .find(|rvt| rvt.type_id == rule_type_id)
620 .map(|rvt| range_values_from_cxx(&rvt.values))
621 }
622
623 /// Returns all possible states for a given `rule_type_id`.
624 ///
625 /// # Arguments
626 /// * `rule_type_id` - The id of the rule type.
627 ///
628 /// # Returns
629 /// An `Option` containing a [RuleValuesByType] enum with either a vector of [Range]s or a
630 /// vector of [DiscreteValue]s. Returns `None` if the `rule_type_id` is not found.
631 pub fn get_possible_states_of_rule_type(&self, rule_type_id: String) -> Option<RuleValuesByType> {
632 if let Some(ranges) = self.range_values_by_type(rule_type_id.clone()) {
633 Some(RuleValuesByType::Ranges(ranges))
634 } else {
635 self.discrete_values_by_type(rule_type_id)
636 .map(RuleValuesByType::DiscreteValues)
637 }
638 }
639}
640
641/// Abstraction for holding the output of [RoadRulebook::rules()] and [RoadRulebook::find_rules()]
642/// methods.
643/// This struct contains a map of [DiscreteValueRule]s and [RangeValueRule]s.
644/// The keys of the map are the ids of the rules.
645/// The values of the map are the rules.
646pub struct QueryResults {
647 pub discrete_value_rules: std::collections::HashMap<String, DiscreteValueRule>,
648 pub range_value_rules: std::collections::HashMap<String, RangeValueRule>,
649}
650
651/// Interface for querying "rules of the road". This interface
652/// provides access to static information about a road network (i.e.,
653/// information determined prior to the beginning of a simulation). Some
654/// rule types may refer to additional dynamic information which will be
655/// provided by other interfaces.
656pub struct RoadRulebook<'a> {
657 pub(super) road_rulebook: &'a maliput_sys::api::rules::ffi::RoadRulebook,
658}
659
660impl<'a> RoadRulebook<'a> {
661 /// Returns the DiscreteValueRule with the specified `id`.
662 ///
663 /// # Arguments
664 /// * `rule_id` - The id of the rule.
665 ///
666 /// # Returns
667 /// The DiscreteValueRule with the given id or None if the id is not in the Rulebook.
668 pub fn get_discrete_value_rule(&self, rule_id: &String) -> Option<DiscreteValueRule> {
669 let discrete_value_rule =
670 maliput_sys::api::rules::ffi::RoadRulebook_GetDiscreteValueRule(self.road_rulebook, rule_id);
671 if discrete_value_rule.is_null() {
672 return None;
673 }
674 Some(DiscreteValueRule { discrete_value_rule })
675 }
676 /// Returns the RangeValueRule with the specified `id`.
677 ///
678 /// # Arguments
679 /// * `rule_id` - The id of the rule.
680 ///
681 /// # Returns
682 /// The RangeValueRule with the given id or None if the id is not in the Rulebook.
683 pub fn get_range_value_rule(&self, rule_id: &String) -> Option<RangeValueRule> {
684 let range_value_rule =
685 maliput_sys::api::rules::ffi::RoadRulebook_GetRangeValueRule(self.road_rulebook, rule_id);
686 if range_value_rule.is_null() {
687 return None;
688 }
689 Some(RangeValueRule { range_value_rule })
690 }
691
692 /// Returns all the rules in the road rulebook.
693 ///
694 /// # Returns
695 /// A [QueryResults] containing all the rules in the road rulebook.
696 pub fn rules(&self) -> QueryResults {
697 let query_results_cpp = maliput_sys::api::rules::ffi::RoadRulebook_Rules(self.road_rulebook);
698 let discrete_value_rules_id =
699 maliput_sys::api::rules::ffi::QueryResults_discrete_value_rules(&query_results_cpp);
700 let range_value_rules_id = maliput_sys::api::rules::ffi::QueryResults_range_value_rules(&query_results_cpp);
701 let mut dvr_map = std::collections::HashMap::new();
702 for rule_id in discrete_value_rules_id {
703 // It is okay to unwrap here since we are iterating valid IDs obtained above.
704 let rule = self.get_discrete_value_rule(&rule_id).unwrap();
705 dvr_map.insert(rule.id(), rule);
706 }
707 let mut rvr_map = std::collections::HashMap::new();
708 for rule_id in range_value_rules_id {
709 // It is okay to unwrap here since we are iterating valid IDs obtained above.
710 let rule = self.get_range_value_rule(&rule_id).unwrap();
711 rvr_map.insert(rule.id(), rule);
712 }
713 QueryResults {
714 discrete_value_rules: dvr_map,
715 range_value_rules: rvr_map,
716 }
717 }
718
719 /// Finds rules that apply to the given lane s ranges.
720 ///
721 /// # Arguments
722 /// * `ranges` - A vector of [super::LaneSRange]s to find rules for.
723 /// * `tolerance` - A tolerance value to use when finding rules.
724 ///
725 /// # Returns
726 /// A [QueryResults] containing the rules that apply to the given lane s ranges.
727 /// If no rules are found, an empty [QueryResults] is returned.
728 ///
729 /// # Errors
730 /// Returns a [MaliputError] if the underlying C++ function fails.
731 pub fn find_rules(&self, ranges: &Vec<super::LaneSRange>, tolerance: f64) -> Result<QueryResults, MaliputError> {
732 let mut ranges_cpp = Vec::new();
733 for range in ranges {
734 ranges_cpp.push(maliput_sys::api::rules::ffi::ConstLaneSRangeRef {
735 lane_s_range: &range.lane_s_range,
736 });
737 }
738 let query_results_cpp =
739 maliput_sys::api::rules::ffi::RoadRulebook_FindRules(self.road_rulebook, &ranges_cpp, tolerance)?;
740
741 let discrete_value_rules_id =
742 maliput_sys::api::rules::ffi::QueryResults_discrete_value_rules(&query_results_cpp);
743 let range_value_rules_id = maliput_sys::api::rules::ffi::QueryResults_range_value_rules(&query_results_cpp);
744 let mut dvr_map = std::collections::HashMap::new();
745 for rule_id in discrete_value_rules_id {
746 if let Some(rule) = self.get_discrete_value_rule(&rule_id) {
747 dvr_map.insert(rule.id(), rule);
748 }
749 }
750 let mut rvr_map = std::collections::HashMap::new();
751 for rule_id in range_value_rules_id {
752 if let Some(rule) = self.get_range_value_rule(&rule_id) {
753 rvr_map.insert(rule.id(), rule);
754 }
755 }
756 Ok(QueryResults {
757 discrete_value_rules: dvr_map,
758 range_value_rules: rvr_map,
759 })
760 }
761}
762
763/// # Rule
764///
765/// A Rule may have multiple states that affect agent behavior while it is
766/// driving through the rule's zone. The possible states of a Rule must be
767/// semantically coherent. The current state of a Rule is given by a
768/// [RuleStateProvider]. States can be:
769///
770/// - range based ([RangeValueRule]).
771/// - discrete ([DiscreteValueRule]).
772///
773/// # DiscreteValueRule
774///
775/// [DiscreteValue]s are defined by a string value.
776/// Semantics of this rule are based on _all_ possible values that this
777/// [DiscreteValueRule::type_id] could have (as specified by RuleRegistry::FindRuleByType()),
778/// not only the subset of values that a specific instance of this rule can
779/// be in.
780pub struct DiscreteValueRule {
781 discrete_value_rule: cxx::UniquePtr<maliput_sys::api::rules::ffi::DiscreteValueRule>,
782}
783
784impl DiscreteValueRule {
785 /// Returns the Id of the rule as a string.
786 ///
787 /// # Returns
788 /// The id of the rule.
789 pub fn id(&self) -> String {
790 maliput_sys::api::rules::ffi::DiscreteValueRule_id(&self.discrete_value_rule)
791 }
792 /// Returns the type of the rule as a string.
793 /// Example: "right-of-way-rule-type-id", "direction-usage-rule-type-id"
794 ///
795 /// # Returns
796 /// The type id of the rule.
797 pub fn type_id(&self) -> String {
798 maliput_sys::api::rules::ffi::DiscreteValueRule_type_id(&self.discrete_value_rule)
799 }
800 /// Returns a [super::LaneSRoute] that represents the zone that the rule applies to.
801 ///
802 /// # Returns
803 /// A [super::LaneSRoute] representing the zone of the rule.
804 pub fn zone(&self) -> super::LaneSRoute {
805 let lane_s_route = maliput_sys::api::rules::ffi::DiscreteValueRule_zone(&self.discrete_value_rule);
806 super::LaneSRoute { lane_s_route }
807 }
808 /// Returns the states of the rule.
809 ///
810 /// # Returns
811 /// A vector of [DiscreteValue]s representing the states of the rule.
812 /// If the rule has no states, an empty vector is returned.
813 pub fn states(&self) -> Vec<DiscreteValue> {
814 discrete_values_from_cxx(self.discrete_value_rule.states())
815 }
816}
817
818impl std::fmt::Debug for DiscreteValueRule {
819 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
820 write!(
821 f,
822 "DiscreteValueRule {{ id: {}, type_id: {}, zone: {:?}, states: {:?} }}",
823 self.id(),
824 self.type_id(),
825 self.zone(),
826 self.states()
827 )
828 }
829}
830
831/// Holds a `Rule` ID and the current state of that `Rule`.
832/// It is usually used as a return type for [super::Intersection::discrete_value_rule_states].
833pub struct DiscreteValueRuleState {
834 /// Rule ID.
835 pub rule_id: String,
836 /// Current state of the rule.
837 pub state: DiscreteValue,
838}
839
840/// # Rule
841///
842/// A Rule may have multiple states that affect agent behavior while it is
843/// driving through the rule's zone. The possible states of a Rule must be
844/// semantically coherent. The current state of a Rule is given by a
845/// [RuleStateProvider]. States can be:
846///
847/// - range based ([RangeValueRule]).
848/// - discrete ([DiscreteValueRule]).
849///
850/// # RangeValueRule
851///
852/// [Range]s describe a numeric range based rule.
853/// Ranges are closed and continuous, defined by a minimum and maximum quantity.
854/// When only one extreme is formally defined, the other should take a
855/// semantically correct value. For example, if a speed limit only specifies a
856/// maximum value, the minimum value is typically zero.
857pub struct RangeValueRule {
858 range_value_rule: cxx::UniquePtr<maliput_sys::api::rules::ffi::RangeValueRule>,
859}
860
861impl RangeValueRule {
862 /// Returns the Id of the rule as a string.
863 ///
864 /// # Returns
865 /// The id of the rule.
866 pub fn id(&self) -> String {
867 maliput_sys::api::rules::ffi::RangeValueRule_id(&self.range_value_rule)
868 }
869 /// Returns the type of the rule as a string.
870 /// Example: "right-of-way-rule-type-id", "direction-usage-rule-type-id"
871 ///
872 /// # Returns
873 /// The type id of the rule.
874 pub fn type_id(&self) -> String {
875 maliput_sys::api::rules::ffi::RangeValueRule_type_id(&self.range_value_rule)
876 }
877 /// Returns a [super::LaneSRoute] that represents the zone that the rule applies to.
878 ///
879 /// # Returns
880 /// A [super::LaneSRoute] representing the zone of the rule.
881 pub fn zone(&self) -> super::LaneSRoute {
882 let lane_s_route = maliput_sys::api::rules::ffi::RangeValueRule_zone(&self.range_value_rule);
883 super::LaneSRoute { lane_s_route }
884 }
885 /// Returns the states of the rule.
886 ///
887 /// # Returns
888 /// A vector of [Range]s representing the states of the rule.
889 /// If the rule has no states, an empty vector is returned.
890 pub fn states(&self) -> Vec<Range> {
891 range_values_from_cxx(self.range_value_rule.states())
892 }
893}
894
895/// Defines a Rule Type.
896///
897/// # RuleType
898///
899/// [RuleType]s provide a way of obtaining a rule type's string defined in
900/// maliput's backend. Since new rule types can be created in a custom manner,
901/// [RuleType] only holds the most common types which are already defined in
902/// the backend.
903#[derive(Display, IntoStaticStr)]
904pub enum RuleType {
905 #[strum(serialize = "Direction-Usage Rule Type")]
906 DirectionUsage,
907 #[strum(serialize = "Right-Of-Way Rule Type")]
908 RightOfWay,
909 #[strum(serialize = "Vehicle-Stop-In-Zone-Behavior Rule Type")]
910 VehicleStopInZoneBehavior,
911 #[strum(serialize = "Speed-Limit Rule Type")]
912 SpeedLimit,
913}
914
915impl RuleType {
916 /// Gets the Rule ID for the [RuleType] and `lane_id`.
917 ///
918 /// # Arguments
919 /// - `lane_id` - The lane ID to get the rule ID from.
920 ///
921 /// # Returns
922 /// A rule ID formatted the way the backend defines it.
923 pub fn get_rule_id(&self, lane_id: &str) -> String {
924 // We rely on maliput_malidrive which define the rule id as:
925 // "<rule_type>/<lane_id>"
926 self.to_string() + "/" + lane_id
927 }
928}
929
930/// Defines a base state for a rule.
931///
932/// # RuleStateBase
933///
934/// - `severity` - The severity of the rule state.
935/// - `related_rules` - A map of related rules. The key is the group name and the value is a vector of rule ids.
936/// - `related_unique_ids` - A map of related unique ids. The key is the group name and the value is a vector of unique ids.
937///
938/// See [DiscreteValueRule] and [RangeValueRule] for more information.
939pub struct RuleStateBase {
940 /// Severity of the rule's state. A non-negative quantity that specifies the
941 /// level of enforcement. The smaller it is, the more strictly the rule is
942 /// enforced. Each rule type can define its own set of severity level
943 /// semantics.
944 severity: i32,
945 related_rules: cxx::UniquePtr<cxx::CxxVector<maliput_sys::api::rules::ffi::RelatedRule>>,
946 related_unique_ids: cxx::UniquePtr<cxx::CxxVector<maliput_sys::api::rules::ffi::RelatedUniqueId>>,
947}
948
949/// A trait representing a possible state of a `Rule`.
950///
951/// A `Rule` can have multiple states that affect agent behavior. This trait
952/// provides a common interface for accessing the properties shared by all
953/// rule states, such as severity and related rules.
954///
955/// This trait is implemented by specific state types like [`DiscreteValue`]
956/// and [`Range`].
957///
958/// # Implementors
959///
960/// When implementing this trait, you must provide an implementation for the
961/// [`get_rule_state()`] method, which gives access to the underlying
962/// [`RuleStateBase`] data. The other methods have default implementations.
963pub trait RuleState {
964 /// Gets the underlying [`RuleStateBase`] that contains common state properties.
965 ///
966 /// # Returns
967 /// A reference to the [`RuleStateBase`] that contains the severity, related rules,
968 /// and related unique ids for the rule state.
969 fn get_rule_state(&self) -> &RuleStateBase;
970
971 /// Returns the severity of the rule state.
972 ///
973 /// # Returns
974 /// An `i32` representing the severity of the rule state.
975 /// 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.
976 fn severity(&self) -> i32 {
977 self.get_rule_state().severity
978 }
979
980 /// Returns a map of related rules ids. The key is the group name and the value is a vector of rule ids.
981 ///
982 /// # Returns
983 /// A map of related rules where the key is the group name and the value is a vector of rule ids.
984 fn related_rules(&self) -> std::collections::HashMap<&String, &Vec<String>> {
985 self.get_rule_state()
986 .related_rules
987 .iter()
988 .map(|rr| (&rr.group_name, &rr.rule_ids))
989 .collect::<std::collections::HashMap<&String, &Vec<String>>>()
990 }
991 /// Returns a map of related unique ids. The key is the group name and the value is a vector of unique ids.
992 ///
993 /// # Returns
994 /// A map of related unique ids where the key is the group name and the value is a vector of unique ids.
995 fn related_unique_ids(&self) -> std::collections::HashMap<&String, &Vec<String>> {
996 self.get_rule_state()
997 .related_unique_ids
998 .iter()
999 .map(|rui| (&rui.group_name, &rui.unique_ids))
1000 .collect::<std::collections::HashMap<&String, &Vec<String>>>()
1001 }
1002}
1003
1004/// Defines a discrete value for a [DiscreteValueRule].
1005/// It extends the [RuleStateBase] with the value of the discrete value.
1006pub struct DiscreteValue {
1007 rule_state: RuleStateBase,
1008 value: String,
1009}
1010
1011impl RuleState for DiscreteValue {
1012 fn get_rule_state(&self) -> &RuleStateBase {
1013 &self.rule_state
1014 }
1015}
1016
1017impl DiscreteValue {
1018 /// Returns the value of the discrete value.
1019 pub fn value(&self) -> &String {
1020 &self.value
1021 }
1022}
1023
1024impl std::fmt::Debug for DiscreteValue {
1025 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1026 write!(
1027 f,
1028 "DiscreteValue {{ value: {}, severity: {}, related_rules: {:?}, related_unique_ids: {:?} }}",
1029 self.value(),
1030 self.severity(),
1031 self.related_rules(),
1032 self.related_unique_ids()
1033 )
1034 }
1035}
1036
1037/// Defines a range value for a [RangeValueRule].
1038/// It extends the [RuleStateBase] with the description, and min and max values of the range.
1039pub struct Range {
1040 rule_state: RuleStateBase,
1041 description: String,
1042 min: f64,
1043 max: f64,
1044}
1045
1046impl RuleState for Range {
1047 fn get_rule_state(&self) -> &RuleStateBase {
1048 &self.rule_state
1049 }
1050}
1051
1052impl Range {
1053 /// Returns the description of the range value.
1054 pub fn description(&self) -> &String {
1055 &self.description
1056 }
1057 /// Returns the minimum value of the range.
1058 pub fn min(&self) -> f64 {
1059 self.min
1060 }
1061 /// Returns the maximum value of the range.
1062 pub fn max(&self) -> f64 {
1063 self.max
1064 }
1065}
1066
1067/// Defines a phase in a traffic rule system.
1068///
1069/// A phase represents a specific state or configuration of traffic signals
1070/// and semantic rules within a traffic control system. Each phase has a unique
1071/// identifier and may include various traffic signal states and rule configurations
1072/// that dictate how traffic should behave during that phase.
1073pub struct Phase {
1074 phase: cxx::UniquePtr<maliput_sys::api::rules::ffi::Phase>,
1075}
1076
1077impl Phase {
1078 /// Gets the id of the [Phase].
1079 ///
1080 /// # Returns
1081 /// The id of the [Phase].
1082 pub fn id(&self) -> String {
1083 maliput_sys::api::rules::ffi::Phase_id(&self.phase)
1084 }
1085
1086 /// Gets the states of all discrete value rules for this phase.
1087 ///
1088 /// # Returns
1089 /// A `HashMap` where the key is the rule ID as a [String] and the value is the
1090 /// [DiscreteValue] state of that rule.
1091 pub fn discrete_value_rule_states(&self) -> HashMap<String, DiscreteValue> {
1092 let rule_states = maliput_sys::api::rules::ffi::Phase_discrete_value_rule_states(&self.phase);
1093 rule_states
1094 .iter()
1095 .map(|state| {
1096 (
1097 state.rule_id.clone(),
1098 discrete_value_from_discrete_value_cxx(&state.state),
1099 )
1100 })
1101 .collect()
1102 }
1103
1104 /// Obtains all [UniqueBulbId]s in the [Phase].
1105 ///
1106 /// # Returns
1107 /// A vector of [UniqueBulbId].
1108 pub fn unique_bulb_ids(&self) -> Vec<UniqueBulbId> {
1109 let unique_bulb_ids = maliput_sys::api::rules::ffi::Phase_unique_bulb_ids(&self.phase);
1110 unique_bulb_ids
1111 .iter()
1112 .map(|bulb_id| UniqueBulbId {
1113 unique_bulb_id: maliput_sys::api::rules::ffi::ptr_from_unique_bulb_id(bulb_id),
1114 })
1115 .collect()
1116 }
1117
1118 /// Returns the [BulbState] corresponding to a `bulb_id`.
1119 ///
1120 /// # Arguments
1121 /// * `unique_bulb_id` - The [UniqueBulbId] to get the [BulbState] from.
1122 ///
1123 /// # Returns
1124 /// The [BulbState] the `unique_bulb_id` is in, or [None] if the [UniqueBulbId] is not in this [Phase].
1125 pub fn bulb_state(&self, unique_bulb_id: &UniqueBulbId) -> Option<BulbState> {
1126 let bulb_state = maliput_sys::api::rules::ffi::Phase_bulb_state(&self.phase, &unique_bulb_id.unique_bulb_id);
1127 if bulb_state.is_null() {
1128 return None;
1129 }
1130 Some(match *bulb_state {
1131 maliput_sys::api::rules::ffi::BulbState::kOff => BulbState::Off,
1132 maliput_sys::api::rules::ffi::BulbState::kOn => BulbState::On,
1133 maliput_sys::api::rules::ffi::BulbState::kBlinking => BulbState::Blinking,
1134 _ => return None,
1135 })
1136 }
1137}
1138
1139/// Defines a phase that comes after another [Phase].
1140/// Used as a return type by:
1141/// - [PhaseRing::get_next_phases].
1142pub struct NextPhase {
1143 /// The next phase.
1144 pub next_phase: Phase,
1145 /// The default time before transitioning to the next phase. This is
1146 /// relative to when the current phase began. It is just a recommendation,
1147 /// the actual duration is determined by the PhaseProvider and may depend on
1148 /// events like a vehicle arriving at a left-turn lane or a pedestrian
1149 /// hitting a crosswalk button.
1150 pub duration_until: Option<f64>,
1151}
1152
1153/// Defines a ring of phases in a traffic rule system.
1154///
1155/// A phase ring represents a sequence of phases that a traffic control system
1156/// cycles through.
1157pub struct PhaseRing {
1158 phase_ring: cxx::UniquePtr<maliput_sys::api::rules::ffi::PhaseRing>,
1159}
1160
1161impl PhaseRing {
1162 /// Gets the id of the [PhaseRing].
1163 ///
1164 /// # Returns
1165 /// The id of the [PhaseRing].
1166 pub fn id(&self) -> String {
1167 maliput_sys::api::rules::ffi::PhaseRing_id(&self.phase_ring)
1168 }
1169
1170 /// Gets a [Phase] by its id
1171 ///
1172 /// # Arguments
1173 /// * `id` - The id of the [Phase].
1174 /// # Returns
1175 /// The [Phase] with the given id.
1176 /// If no [Phase] is found with the given id, return None.
1177 pub fn get_phase(&self, id: &String) -> Option<Phase> {
1178 let phase = maliput_sys::api::rules::ffi::PhaseRing_GetPhase(&self.phase_ring, id);
1179 if phase.is_null() {
1180 return None;
1181 }
1182 Some(Phase { phase })
1183 }
1184
1185 /// Returns the ids of all Phases in the PhaseRing.
1186 ///
1187 /// # Returns
1188 /// A vector of strings representing the ids of all Phases in the PhaseRing.
1189 pub fn phases(&self) -> Vec<String> {
1190 maliput_sys::api::rules::ffi::PhaseRing_phases_ids(&self.phase_ring)
1191 }
1192
1193 /// Returns the next phases for a given phase `id`.
1194 ///
1195 /// # Arguments
1196 /// * `id` - The id of the phase to get the next phases from.
1197 ///
1198 /// # Returns
1199 /// A `Result` containing a vector of [NextPhase]s.
1200 ///
1201 /// # Errors
1202 /// Returns a [MaliputError] if the provided `id` is not found in the [PhaseRing].
1203 pub fn get_next_phases(&self, id: &String) -> Result<Vec<NextPhase>, MaliputError> {
1204 let next_phases = maliput_sys::api::rules::ffi::PhaseRing_GetNextPhases(&self.phase_ring, id)?;
1205 Ok(next_phases
1206 .iter()
1207 .map(|np| NextPhase {
1208 next_phase: Phase {
1209 phase: maliput_sys::api::rules::ffi::PhaseRing_GetPhase(&self.phase_ring, &np.phase_id),
1210 },
1211 duration_until: if np.duration_until.is_null() {
1212 None
1213 } else {
1214 Some(np.duration_until.value)
1215 },
1216 })
1217 .collect())
1218 }
1219}
1220
1221/// Defines a book of phase rings in a traffic rule system.
1222pub struct PhaseRingBook<'a> {
1223 pub(super) phase_ring_book: &'a maliput_sys::api::rules::ffi::PhaseRingBook,
1224}
1225
1226impl<'a> PhaseRingBook<'a> {
1227 /// Returns the ids of all PhaseRings in the PhaseRingBook.
1228 ///
1229 /// # Returns
1230 /// A vector of strings representing the ids of all PhaseRings in the PhaseRingBook.
1231 pub fn get_phase_rings_ids(&self) -> Vec<String> {
1232 maliput_sys::api::rules::ffi::PhaseRingBook_GetPhaseRingsId(self.phase_ring_book)
1233 }
1234
1235 /// Returns the PhaseRing with the specified `id`.
1236 ///
1237 /// # Arguments
1238 /// * `phase_ring_id` - The id of the phase ring.
1239 ///
1240 /// # Returns
1241 /// The PhaseRing with the given id or None if the id is not in the PhaseRingBook.
1242 pub fn get_phase_ring(&self, phase_ring_id: &String) -> Option<PhaseRing> {
1243 let phase_ring = maliput_sys::api::rules::ffi::PhaseRingBook_GetPhaseRing(self.phase_ring_book, phase_ring_id);
1244 if phase_ring.is_null() {
1245 return None;
1246 }
1247 Some(PhaseRing { phase_ring })
1248 }
1249
1250 /// Finds the [PhaseRing] that contains the rule with the specified `rule_id`.
1251 ///
1252 /// # Arguments
1253 /// * `rule_id` - The id of the rule.
1254 ///
1255 /// # Returns
1256 /// The [PhaseRing] that contains the rule with the given id or `None` if no [PhaseRing] is found.
1257 pub fn find_phase_ring(&self, rule_id: &String) -> Option<PhaseRing> {
1258 let phase_ring = maliput_sys::api::rules::ffi::PhaseRingBook_FindPhaseRing(self.phase_ring_book, rule_id);
1259 if phase_ring.is_null() {
1260 return None;
1261 }
1262 Some(PhaseRing { phase_ring })
1263 }
1264}
1265
1266/// Defines a next state of a generic type.
1267pub struct NextState<T> {
1268 /// The next state.
1269 pub next_state: T,
1270 /// The default time before transitioning to the next state. This is
1271 /// relative to when the current state began. It is just a recommendation,
1272 /// the actual duration is determined by the StateProvider and may depend on
1273 /// events like a vehicle arriving at a left-turn lane or a pedestrian
1274 /// hitting a crosswalk button.
1275 pub duration_until: Option<f64>,
1276}
1277
1278/// Holds the current and possible next state of a system.
1279/// It is usually returned by the different types of state providers.
1280pub struct StateProviderQuery<T> {
1281 /// The current state.
1282 pub state: T,
1283 /// The next state.
1284 pub next: Option<NextState<T>>,
1285}
1286
1287/// Alias for the [StateProviderQuery] returned by [PhaseProvider::get_phase].
1288pub type PhaseStateProviderQuery = StateProviderQuery<String>;
1289
1290/// Defines a phase provider.
1291///
1292/// A phase provider is able to get the current phase from a phase-based system.
1293pub struct PhaseProvider<'a> {
1294 pub(super) phase_provider: &'a maliput_sys::api::rules::ffi::PhaseProvider,
1295}
1296
1297impl<'a> PhaseProvider<'a> {
1298 /// Returns the [PhaseStateProviderQuery] for the specified `phase_ring_id`.
1299 ///
1300 /// The states are represented with Strings containing the IDs of each [Phase].
1301 ///
1302 /// # Arguments
1303 /// * `phase_ring_id` - The id of the phase ring.
1304 ///
1305 /// # Returns
1306 /// An `Option` containing the [PhaseStateProviderQuery] for the given `phase_ring_id`.
1307 /// Returns `None` if no phase provider is found for the given id.
1308 pub fn get_phase(&self, phase_ring_id: &String) -> Option<PhaseStateProviderQuery> {
1309 let phase_state = maliput_sys::api::rules::ffi::PhaseProvider_GetPhase(self.phase_provider, phase_ring_id);
1310 if phase_state.is_null() {
1311 return None;
1312 }
1313
1314 let next_state = maliput_sys::api::rules::ffi::PhaseStateProvider_next(&phase_state);
1315 let next_phase = if next_state.is_null() {
1316 None
1317 } else {
1318 Some(NextState {
1319 next_state: next_state.phase_id.clone(),
1320 duration_until: if next_state.duration_until.is_null() {
1321 None
1322 } else {
1323 Some(next_state.duration_until.value)
1324 },
1325 })
1326 };
1327
1328 Some(StateProviderQuery {
1329 state: maliput_sys::api::rules::ffi::PhaseStateProvider_state(&phase_state),
1330 next: next_phase,
1331 })
1332 }
1333}
1334
1335/// Provides the dynamic state of [DiscreteValueRule]s.
1336///
1337/// While a [RoadRulebook] provides the static definitions of rules, a
1338/// `DiscreteValueRuleStateProvider` provides the current state of those rules
1339/// at runtime. This allows for querying what state a rule is currently in,
1340/// which is essential for dynamic systems where rule states can change over
1341/// time (e.g., traffic light phases changing).
1342pub struct DiscreteValueRuleStateProvider<'a> {
1343 pub(super) state_provider: &'a maliput_sys::api::rules::ffi::DiscreteValueRuleStateProvider,
1344}
1345
1346impl<'a> DiscreteValueRuleStateProvider<'a> {
1347 /// Gets a state from the provider based on it's `rule_id`.
1348 ///
1349 /// # Arguments
1350 /// * `rule_id` - A Rule ID.
1351 ///
1352 /// # Returns
1353 /// An Option containing the [StateProviderQuery] with a [DiscreteValue] if the `rule_id` matches with any rule.
1354 /// Otherwise, None is returned.
1355 pub fn get_state_by_rule_id(&self, rule_id: &String) -> Option<StateProviderQuery<DiscreteValue>> {
1356 let query_state =
1357 maliput_sys::api::rules::ffi::DiscreteValueRuleStateProvider_GetStateById(self.state_provider, rule_id);
1358 Self::next_state_from_cxx_query(query_state)
1359 }
1360
1361 /// Gets a state from the provider if there is a `rule_type` in the received `road_position`.
1362 ///
1363 /// # Arguments
1364 /// * `road_position` - A position in the road geometry.
1365 /// * `rule_type` - A Rule Type.
1366 /// * `tolerance` - The tolerance in which to look for the Rule of type `rule_type` around the `road_position`.
1367 ///
1368 /// # Returns
1369 /// An Option containing the [StateProviderQuery] with a [DiscreteValue] if `rule_type` matches with any rule's type near `road_position`.
1370 /// Otherwise, None is returned.
1371 pub fn get_state_by_rule_type(
1372 &self,
1373 road_position: &RoadPosition,
1374 rule_type: RuleType,
1375 tolerance: f64,
1376 ) -> Option<StateProviderQuery<DiscreteValue>> {
1377 let query_state = maliput_sys::api::rules::ffi::DiscreteValueRuleStateProvider_GetStateByType(
1378 self.state_provider,
1379 &road_position.rp,
1380 &rule_type.to_string(),
1381 tolerance,
1382 );
1383 Self::next_state_from_cxx_query(query_state)
1384 }
1385
1386 // Internal helper to avoid code duplication.
1387 fn next_state_from_cxx_query(
1388 query_state: cxx::UniquePtr<maliput_sys::api::rules::ffi::DiscreteValueRuleStateProviderQuery>,
1389 ) -> Option<StateProviderQuery<DiscreteValue>> {
1390 if query_state.is_null() {
1391 return None;
1392 }
1393 let next_state = maliput_sys::api::rules::ffi::DiscreteValueRuleStateProviderQuery_next(&query_state);
1394 Some(StateProviderQuery {
1395 state: discrete_value_from_discrete_value_cxx(
1396 &maliput_sys::api::rules::ffi::DiscreteValueRuleStateProviderQuery_state(&query_state),
1397 ),
1398 next: if next_state.is_null() {
1399 None
1400 } else {
1401 Some(NextState {
1402 next_state: discrete_value_from_discrete_value_cxx(&next_state.state),
1403 duration_until: if next_state.duration_until.is_null() {
1404 None
1405 } else {
1406 Some(next_state.duration_until.value)
1407 },
1408 })
1409 },
1410 })
1411 }
1412}
1413
1414/// Provides the dynamic state of [RangeValueRule]s.
1415///
1416/// While a [RoadRulebook] provides the static definitions of rules, a
1417/// `RangeValueRuleStateProvider` provides the current state of those rules
1418/// at runtime. This allows for querying what state a rule is currently in,
1419/// which is essential for dynamic systems where rule states can change over
1420/// time (e.g., variable speed limits based on types of roads).
1421pub struct RangeValueRuleStateProvider<'a> {
1422 pub(super) state_provider: &'a maliput_sys::api::rules::ffi::RangeValueRuleStateProvider,
1423}
1424
1425impl<'a> RangeValueRuleStateProvider<'a> {
1426 /// Gets a state from the provider based on it's `rule_id`.
1427 ///
1428 /// # Arguments
1429 /// * `rule_id` - A Rule ID.
1430 ///
1431 /// # Returns
1432 /// An Option containing the [StateProviderQuery] with a [Range] if the `rule_id` matches with any rule.
1433 /// Otherwise, None is returned.
1434 pub fn get_state_by_rule_id(&self, rule_id: &String) -> Option<StateProviderQuery<Range>> {
1435 let query_state =
1436 maliput_sys::api::rules::ffi::RangeValueRuleStateProvider_GetStateById(self.state_provider, rule_id);
1437 Self::next_state_from_cxx_query(query_state)
1438 }
1439
1440 /// Gets a state from the provider if there is a `rule_type` in the received `road_position`.
1441 ///
1442 /// # Arguments
1443 /// * `road_position` - A position in the road geometry.
1444 /// * `rule_type` - A Rule Type.
1445 /// * `tolerance` - The tolerance in which to look for the Rule of type `rule_type` around the `road_position`.
1446 ///
1447 /// # Returns
1448 /// An Option containing the [StateProviderQuery] with a [Range] if `rule_type` matches with any rule's type near `road_position`.
1449 /// Otherwise, None is returned.
1450 pub fn get_state_by_rule_type(
1451 &self,
1452 road_position: &RoadPosition,
1453 rule_type: RuleType,
1454 tolerance: f64,
1455 ) -> Option<StateProviderQuery<Range>> {
1456 let query_state = maliput_sys::api::rules::ffi::RangeValueRuleStateProvider_GetStateByType(
1457 self.state_provider,
1458 &road_position.rp,
1459 &rule_type.to_string(),
1460 tolerance,
1461 );
1462 Self::next_state_from_cxx_query(query_state)
1463 }
1464
1465 // Internal helper to avoid code duplication.
1466 fn next_state_from_cxx_query(
1467 query_state: cxx::UniquePtr<maliput_sys::api::rules::ffi::RangeValueRuleStateProviderQuery>,
1468 ) -> Option<StateProviderQuery<Range>> {
1469 if query_state.is_null() {
1470 return None;
1471 }
1472 let next_state = maliput_sys::api::rules::ffi::RangeValueRuleStateProviderQuery_next(&query_state);
1473 Some(StateProviderQuery {
1474 state: range_value_from_range_value_cxx(
1475 &maliput_sys::api::rules::ffi::RangeValueRuleStateProviderQuery_state(&query_state),
1476 ),
1477 next: if next_state.is_null() {
1478 None
1479 } else {
1480 Some(NextState {
1481 next_state: range_value_from_range_value_cxx(&next_state.state),
1482 duration_until: if next_state.duration_until.is_null() {
1483 None
1484 } else {
1485 Some(next_state.duration_until.value)
1486 },
1487 })
1488 },
1489 })
1490 }
1491}
1492
1493// Auxiliary method to create a [Vec<Range>] from a [cxx::Vector<RangeValueRuleRange>].
1494fn range_values_from_cxx(
1495 range_values_cxx: &cxx::Vector<maliput_sys::api::rules::ffi::RangeValueRuleRange>,
1496) -> Vec<Range> {
1497 range_values_cxx
1498 .iter()
1499 .map(|range| Range {
1500 rule_state: RuleStateBase {
1501 severity: maliput_sys::api::rules::ffi::RangeValueRuleRange_severity(range),
1502 related_rules: maliput_sys::api::rules::ffi::RangeValueRuleRange_related_rules(range),
1503 related_unique_ids: maliput_sys::api::rules::ffi::RangeValueRuleRange_related_unique_ids(range),
1504 },
1505 description: maliput_sys::api::rules::ffi::RangeValueRuleRange_description(range),
1506 min: maliput_sys::api::rules::ffi::RangeValueRuleRange_min(range),
1507 max: maliput_sys::api::rules::ffi::RangeValueRuleRange_max(range),
1508 })
1509 .collect()
1510}
1511
1512// Auxiliary method to create a [Vec<DiscreteValue>] from a [cxx::Vector<DiscreteValueRuleDiscreteValue>].
1513fn discrete_values_from_cxx(
1514 discrete_values_cxx: &cxx::Vector<maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue>,
1515) -> Vec<DiscreteValue> {
1516 discrete_values_cxx
1517 .iter()
1518 .map(discrete_value_from_discrete_value_cxx)
1519 .collect()
1520}
1521
1522// Auxiliary method to create a [DiscreteValue] from a [maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue].
1523pub(crate) fn discrete_value_from_discrete_value_cxx(
1524 discrete_value: &maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue,
1525) -> DiscreteValue {
1526 DiscreteValue {
1527 rule_state: RuleStateBase {
1528 severity: maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue_severity(discrete_value),
1529 related_rules: maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue_related_rules(discrete_value),
1530 related_unique_ids: maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue_related_unique_ids(
1531 discrete_value,
1532 ),
1533 },
1534 value: maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue_value(discrete_value),
1535 }
1536}
1537
1538// Auxiliary method to create a [Range] from a [maliput_sys::api::rules::ffi::RangeValueRuleRange].
1539fn range_value_from_range_value_cxx(range: &maliput_sys::api::rules::ffi::RangeValueRuleRange) -> Range {
1540 Range {
1541 rule_state: RuleStateBase {
1542 severity: maliput_sys::api::rules::ffi::RangeValueRuleRange_severity(range),
1543 related_rules: maliput_sys::api::rules::ffi::RangeValueRuleRange_related_rules(range),
1544 related_unique_ids: maliput_sys::api::rules::ffi::RangeValueRuleRange_related_unique_ids(range),
1545 },
1546 description: maliput_sys::api::rules::ffi::RangeValueRuleRange_description(range),
1547 min: maliput_sys::api::rules::ffi::RangeValueRuleRange_min(range),
1548 max: maliput_sys::api::rules::ffi::RangeValueRuleRange_max(range),
1549 }
1550}