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::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 [crate::api::InertialPosition] representing the position of the [TrafficLight] in the road network.
109 pub fn position_road_network(&self) -> crate::api::InertialPosition {
110 let inertial_position = maliput_sys::api::rules::ffi::TrafficLight_position_road_network(self.traffic_light);
111 crate::api::InertialPosition { ip: inertial_position }
112 }
113
114 /// Get the orientation of the [TrafficLight] in the road network.
115 ///
116 /// # Returns
117 /// An [crate::api::Rotation] representing the orientation of the [TrafficLight] in the road network.
118 pub fn orientation_road_network(&self) -> crate::api::Rotation {
119 let rotation = maliput_sys::api::rules::ffi::TrafficLight_orientation_road_network(self.traffic_light);
120 crate::api::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 [crate::api::InertialPosition] representing the position of the [Bulb] in the bulb group.
239 pub fn position_bulb_group(&self) -> crate::api::InertialPosition {
240 let inertial_position = maliput_sys::api::rules::ffi::Bulb_position_bulb_group(self.bulb);
241 crate::api::InertialPosition { ip: inertial_position }
242 }
243
244 /// Get the orientation of the [Bulb] in the bulb group.
245 ///
246 /// # Returns
247 /// An [crate::api::Rotation] representing the orientation of the [Bulb] in the bulb group.
248 pub fn orientation_bulb_group(&self) -> crate::api::Rotation {
249 let rotation = maliput_sys::api::rules::ffi::Bulb_orientation_bulb_group(self.bulb);
250 crate::api::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 [crate::api::InertialPosition] representing the position of the [BulbGroup] in the traffic light.
399 pub fn position_traffic_light(&self) -> crate::api::InertialPosition {
400 let inertial_position = maliput_sys::api::rules::ffi::BulbGroup_position_traffic_light(self.bulb_group);
401 crate::api::InertialPosition { ip: inertial_position }
402 }
403
404 /// Gets the orientation of the [BulbGroup] in the traffic light.
405 ///
406 /// # Returns
407 /// An [crate::api::Rotation] representing the orientation of the [BulbGroup] in the traffic light.
408 pub fn orientation_traffic_light(&self) -> crate::api::Rotation {
409 let rotation = maliput_sys::api::rules::ffi::BulbGroup_orientation_traffic_light(self.bulb_group);
410 crate::api::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 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 [crate::api::LaneSRoute] that represents the zone that the rule applies to.
801 ///
802 /// # Returns
803 /// A [crate::api::LaneSRoute] representing the zone of the rule.
804 pub fn zone(&self) -> crate::api::LaneSRoute {
805 let lane_s_route = maliput_sys::api::rules::ffi::DiscreteValueRule_zone(&self.discrete_value_rule);
806 crate::api::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/// # Rule
832///
833/// A Rule may have multiple states that affect agent behavior while it is
834/// driving through the rule's zone. The possible states of a Rule must be
835/// semantically coherent. The current state of a Rule is given by a
836/// [RuleStateProvider]. States can be:
837///
838/// - range based ([RangeValueRule]).
839/// - discrete ([DiscreteValueRule]).
840///
841/// # RangeValueRule
842///
843/// [Range]s describe a numeric range based rule.
844/// Ranges are closed and continuous, defined by a minimum and maximum quantity.
845/// When only one extreme is formally defined, the other should take a
846/// semantically correct value. For example, if a speed limit only specifies a
847/// maximum value, the minimum value is typically zero.
848pub struct RangeValueRule {
849 range_value_rule: cxx::UniquePtr<maliput_sys::api::rules::ffi::RangeValueRule>,
850}
851
852impl RangeValueRule {
853 /// Returns the Id of the rule as a string.
854 ///
855 /// # Returns
856 /// The id of the rule.
857 pub fn id(&self) -> String {
858 maliput_sys::api::rules::ffi::RangeValueRule_id(&self.range_value_rule)
859 }
860 /// Returns the type of the rule as a string.
861 /// Example: "right-of-way-rule-type-id", "direction-usage-rule-type-id"
862 ///
863 /// # Returns
864 /// The type id of the rule.
865 pub fn type_id(&self) -> String {
866 maliput_sys::api::rules::ffi::RangeValueRule_type_id(&self.range_value_rule)
867 }
868 /// Returns a [crate::api::LaneSRoute] that represents the zone that the rule applies to.
869 ///
870 /// # Returns
871 /// A [crate::api::LaneSRoute] representing the zone of the rule.
872 pub fn zone(&self) -> crate::api::LaneSRoute {
873 let lane_s_route = maliput_sys::api::rules::ffi::RangeValueRule_zone(&self.range_value_rule);
874 crate::api::LaneSRoute { lane_s_route }
875 }
876 /// Returns the states of the rule.
877 ///
878 /// # Returns
879 /// A vector of [Range]s representing the states of the rule.
880 /// If the rule has no states, an empty vector is returned.
881 pub fn states(&self) -> Vec<Range> {
882 range_values_from_cxx(self.range_value_rule.states())
883 }
884}
885
886/// Defines a Rule Type.
887///
888/// # RuleType
889///
890/// [RuleType]s provide a way of obtaining a rule type's string defined in
891/// maliput's backend. Since new rule types can be created in a custom manner,
892/// [RuleType] only holds the most common types which are already defined in
893/// the backend.
894#[derive(Display, IntoStaticStr)]
895pub enum RuleType {
896 #[strum(serialize = "Direction-Usage Rule Type")]
897 DirectionUsage,
898 #[strum(serialize = "Right-Of-Way Rule Type")]
899 RightOfWay,
900 #[strum(serialize = "Vehicle-Stop-In-Zone-Behavior Rule Type")]
901 VehicleStopInZoneBehavior,
902 #[strum(serialize = "Speed-Limit Rule Type")]
903 SpeedLimit,
904}
905
906impl RuleType {
907 /// Gets the Rule ID for the [RuleType] and `lane_id`.
908 ///
909 /// # Arguments
910 /// - `lane_id` - The lane ID to get the rule ID from.
911 ///
912 /// # Returns
913 /// A rule ID formatted the way the backend defines it.
914 pub fn get_rule_id(&self, lane_id: &str) -> String {
915 // We rely on maliput_malidrive which define the rule id as:
916 // "<rule_type>/<lane_id>"
917 self.to_string() + "/" + lane_id
918 }
919}
920
921/// Defines a base state for a rule.
922///
923/// # RuleStateBase
924///
925/// - `severity` - The severity of the rule state.
926/// - `related_rules` - A map of related rules. The key is the group name and the value is a vector of rule ids.
927/// - `related_unique_ids` - A map of related unique ids. The key is the group name and the value is a vector of unique ids.
928///
929/// See [DiscreteValueRule] and [RangeValueRule] for more information.
930pub struct RuleStateBase {
931 /// Severity of the rule's state. A non-negative quantity that specifies the
932 /// level of enforcement. The smaller it is, the more strictly the rule is
933 /// enforced. Each rule type can define its own set of severity level
934 /// semantics.
935 severity: i32,
936 related_rules: cxx::UniquePtr<cxx::CxxVector<maliput_sys::api::rules::ffi::RelatedRule>>,
937 related_unique_ids: cxx::UniquePtr<cxx::CxxVector<maliput_sys::api::rules::ffi::RelatedUniqueId>>,
938}
939
940/// A trait representing a possible state of a `Rule`.
941///
942/// A `Rule` can have multiple states that affect agent behavior. This trait
943/// provides a common interface for accessing the properties shared by all
944/// rule states, such as severity and related rules.
945///
946/// This trait is implemented by specific state types like [`DiscreteValue`]
947/// and [`Range`].
948///
949/// # Implementors
950///
951/// When implementing this trait, you must provide an implementation for the
952/// [`get_rule_state()`] method, which gives access to the underlying
953/// [`RuleStateBase`] data. The other methods have default implementations.
954pub trait RuleState {
955 /// Gets the underlying [`RuleStateBase`] that contains common state properties.
956 ///
957 /// # Returns
958 /// A reference to the [`RuleStateBase`] that contains the severity, related rules,
959 /// and related unique ids for the rule state.
960 fn get_rule_state(&self) -> &RuleStateBase;
961
962 /// Returns the severity of the rule state.
963 ///
964 /// # Returns
965 /// An `i32` representing the severity of the rule state.
966 /// 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.
967 fn severity(&self) -> i32 {
968 self.get_rule_state().severity
969 }
970
971 /// Returns a map of related rules ids. The key is the group name and the value is a vector of rule ids.
972 ///
973 /// # Returns
974 /// A map of related rules where the key is the group name and the value is a vector of rule ids.
975 fn related_rules(&self) -> std::collections::HashMap<&String, &Vec<String>> {
976 self.get_rule_state()
977 .related_rules
978 .iter()
979 .map(|rr| (&rr.group_name, &rr.rule_ids))
980 .collect::<std::collections::HashMap<&String, &Vec<String>>>()
981 }
982 /// Returns a map of related unique ids. The key is the group name and the value is a vector of unique ids.
983 ///
984 /// # Returns
985 /// A map of related unique ids where the key is the group name and the value is a vector of unique ids.
986 fn related_unique_ids(&self) -> std::collections::HashMap<&String, &Vec<String>> {
987 self.get_rule_state()
988 .related_unique_ids
989 .iter()
990 .map(|rui| (&rui.group_name, &rui.unique_ids))
991 .collect::<std::collections::HashMap<&String, &Vec<String>>>()
992 }
993}
994
995/// Defines a discrete value for a [DiscreteValueRule].
996/// It extends the [RuleStateBase] with the value of the discrete value.
997pub struct DiscreteValue {
998 rule_state: RuleStateBase,
999 value: String,
1000}
1001
1002impl RuleState for DiscreteValue {
1003 fn get_rule_state(&self) -> &RuleStateBase {
1004 &self.rule_state
1005 }
1006}
1007
1008impl DiscreteValue {
1009 /// Returns the value of the discrete value.
1010 pub fn value(&self) -> &String {
1011 &self.value
1012 }
1013}
1014
1015impl std::fmt::Debug for DiscreteValue {
1016 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1017 write!(
1018 f,
1019 "DiscreteValue {{ value: {}, severity: {}, related_rules: {:?}, related_unique_ids: {:?} }}",
1020 self.value(),
1021 self.severity(),
1022 self.related_rules(),
1023 self.related_unique_ids()
1024 )
1025 }
1026}
1027
1028/// Defines a range value for a [RangeValueRule].
1029/// It extends the [RuleStateBase] with the description, and min and max values of the range.
1030pub struct Range {
1031 rule_state: RuleStateBase,
1032 description: String,
1033 min: f64,
1034 max: f64,
1035}
1036
1037impl RuleState for Range {
1038 fn get_rule_state(&self) -> &RuleStateBase {
1039 &self.rule_state
1040 }
1041}
1042
1043impl Range {
1044 /// Returns the description of the range value.
1045 pub fn description(&self) -> &String {
1046 &self.description
1047 }
1048 /// Returns the minimum value of the range.
1049 pub fn min(&self) -> f64 {
1050 self.min
1051 }
1052 /// Returns the maximum value of the range.
1053 pub fn max(&self) -> f64 {
1054 self.max
1055 }
1056}
1057
1058/// Defines a phase in a traffic rule system.
1059///
1060/// A phase represents a specific state or configuration of traffic signals
1061/// and semantic rules within a traffic control system. Each phase has a unique
1062/// identifier and may include various traffic signal states and rule configurations
1063/// that dictate how traffic should behave during that phase.
1064pub struct Phase {
1065 phase: cxx::UniquePtr<maliput_sys::api::rules::ffi::Phase>,
1066}
1067
1068impl Phase {
1069 /// Gets the id of the [Phase].
1070 ///
1071 /// # Returns
1072 /// The id of the [Phase].
1073 pub fn id(&self) -> String {
1074 maliput_sys::api::rules::ffi::Phase_id(&self.phase)
1075 }
1076
1077 /// Gets the states of all discrete value rules for this phase.
1078 ///
1079 /// # Returns
1080 /// A `HashMap` where the key is the rule ID as a [String] and the value is the
1081 /// [DiscreteValue] state of that rule.
1082 pub fn discrete_value_rule_states(&self) -> HashMap<String, DiscreteValue> {
1083 let rule_states = maliput_sys::api::rules::ffi::Phase_discrete_value_rule_states(&self.phase);
1084 rule_states
1085 .iter()
1086 .map(|state| {
1087 (
1088 state.rule_id.clone(),
1089 discrete_value_from_discrete_value_cxx(&state.state),
1090 )
1091 })
1092 .collect()
1093 }
1094
1095 /// Obtains all [UniqueBulbId]s in the [Phase].
1096 ///
1097 /// # Returns
1098 /// A vector of [UniqueBulbId].
1099 pub fn unique_bulb_ids(&self) -> Vec<UniqueBulbId> {
1100 let unique_bulb_ids = maliput_sys::api::rules::ffi::Phase_unique_bulb_ids(&self.phase);
1101 unique_bulb_ids
1102 .iter()
1103 .map(|bulb_id| UniqueBulbId {
1104 unique_bulb_id: maliput_sys::api::rules::ffi::ptr_from_unique_bulb_id(bulb_id),
1105 })
1106 .collect()
1107 }
1108
1109 /// Returns the [BulbState] corresponding to a `bulb_id`.
1110 ///
1111 /// # Arguments
1112 /// * `unique_bulb_id` - The [UniqueBulbId] to get the [BulbState] from.
1113 ///
1114 /// # Returns
1115 /// The [BulbState] the `unique_bulb_id` is in, or [None] if the [UniqueBulbId] is not in this [Phase].
1116 pub fn bulb_state(&self, unique_bulb_id: &UniqueBulbId) -> Option<BulbState> {
1117 let bulb_state = maliput_sys::api::rules::ffi::Phase_bulb_state(&self.phase, &unique_bulb_id.unique_bulb_id);
1118 if bulb_state.is_null() {
1119 return None;
1120 }
1121 Some(match *bulb_state {
1122 maliput_sys::api::rules::ffi::BulbState::kOff => BulbState::Off,
1123 maliput_sys::api::rules::ffi::BulbState::kOn => BulbState::On,
1124 maliput_sys::api::rules::ffi::BulbState::kBlinking => BulbState::Blinking,
1125 _ => return None,
1126 })
1127 }
1128}
1129
1130/// Defines a phase that comes after another [Phase].
1131/// Used as a return type by:
1132/// - [PhaseRing::get_next_phases].
1133pub struct NextPhase {
1134 /// The next phase.
1135 pub next_phase: Phase,
1136 /// The default time before transitioning to the next phase. This is
1137 /// relative to when the current phase began. It is just a recommendation,
1138 /// the actual duration is determined by the PhaseProvider and may depend on
1139 /// events like a vehicle arriving at a left-turn lane or a pedestrian
1140 /// hitting a crosswalk button.
1141 pub duration_until: Option<f64>,
1142}
1143
1144/// Defines a ring of phases in a traffic rule system.
1145///
1146/// A phase ring represents a sequence of phases that a traffic control system
1147/// cycles through.
1148pub struct PhaseRing {
1149 phase_ring: cxx::UniquePtr<maliput_sys::api::rules::ffi::PhaseRing>,
1150}
1151
1152impl PhaseRing {
1153 /// Gets the id of the [PhaseRing].
1154 ///
1155 /// # Returns
1156 /// The id of the [PhaseRing].
1157 pub fn id(&self) -> String {
1158 maliput_sys::api::rules::ffi::PhaseRing_id(&self.phase_ring)
1159 }
1160
1161 /// Gets a [Phase] by its id
1162 ///
1163 /// # Arguments
1164 /// * `id` - The id of the [Phase].
1165 /// # Returns
1166 /// The [Phase] with the given id.
1167 /// If no [Phase] is found with the given id, return None.
1168 pub fn get_phase(&self, id: &String) -> Option<Phase> {
1169 let phase = maliput_sys::api::rules::ffi::PhaseRing_GetPhase(&self.phase_ring, id);
1170 if phase.is_null() {
1171 return None;
1172 }
1173 Some(Phase { phase })
1174 }
1175
1176 /// Returns the ids of all Phases in the PhaseRing.
1177 ///
1178 /// # Returns
1179 /// A vector of strings representing the ids of all Phases in the PhaseRing.
1180 pub fn phases(&self) -> Vec<String> {
1181 maliput_sys::api::rules::ffi::PhaseRing_phases_ids(&self.phase_ring)
1182 }
1183
1184 /// Returns the next phases for a given phase `id`.
1185 ///
1186 /// # Arguments
1187 /// * `id` - The id of the phase to get the next phases from.
1188 ///
1189 /// # Returns
1190 /// A `Result` containing a vector of [NextPhase]s.
1191 ///
1192 /// # Errors
1193 /// Returns a [MaliputError] if the provided `id` is not found in the [PhaseRing].
1194 pub fn get_next_phases(&self, id: &String) -> Result<Vec<NextPhase>, MaliputError> {
1195 let next_phases = maliput_sys::api::rules::ffi::PhaseRing_GetNextPhases(&self.phase_ring, id)?;
1196 Ok(next_phases
1197 .iter()
1198 .map(|np| NextPhase {
1199 next_phase: Phase {
1200 phase: maliput_sys::api::rules::ffi::PhaseRing_GetPhase(&self.phase_ring, &np.phase_id),
1201 },
1202 duration_until: if np.duration_until.is_null() {
1203 None
1204 } else {
1205 Some(np.duration_until.value)
1206 },
1207 })
1208 .collect())
1209 }
1210}
1211
1212/// Defines a book of phase rings in a traffic rule system.
1213pub struct PhaseRingBook<'a> {
1214 pub(super) phase_ring_book: &'a maliput_sys::api::rules::ffi::PhaseRingBook,
1215}
1216
1217impl<'a> PhaseRingBook<'a> {
1218 /// Returns the ids of all PhaseRings in the PhaseRingBook.
1219 ///
1220 /// # Returns
1221 /// A vector of strings representing the ids of all PhaseRings in the PhaseRingBook.
1222 pub fn get_phase_rings_ids(&self) -> Vec<String> {
1223 maliput_sys::api::rules::ffi::PhaseRingBook_GetPhaseRingsId(self.phase_ring_book)
1224 }
1225
1226 /// Returns the PhaseRing with the specified `id`.
1227 ///
1228 /// # Arguments
1229 /// * `phase_ring_id` - The id of the phase ring.
1230 ///
1231 /// # Returns
1232 /// The PhaseRing with the given id or None if the id is not in the PhaseRingBook.
1233 pub fn get_phase_ring(&self, phase_ring_id: &String) -> Option<PhaseRing> {
1234 let phase_ring = maliput_sys::api::rules::ffi::PhaseRingBook_GetPhaseRing(self.phase_ring_book, phase_ring_id);
1235 if phase_ring.is_null() {
1236 return None;
1237 }
1238 Some(PhaseRing { phase_ring })
1239 }
1240
1241 /// Finds the [PhaseRing] that contains the rule with the specified `rule_id`.
1242 ///
1243 /// # Arguments
1244 /// * `rule_id` - The id of the rule.
1245 ///
1246 /// # Returns
1247 /// The [PhaseRing] that contains the rule with the given id or `None` if no [PhaseRing] is found.
1248 pub fn find_phase_ring(&self, rule_id: &String) -> Option<PhaseRing> {
1249 let phase_ring = maliput_sys::api::rules::ffi::PhaseRingBook_FindPhaseRing(self.phase_ring_book, rule_id);
1250 if phase_ring.is_null() {
1251 return None;
1252 }
1253 Some(PhaseRing { phase_ring })
1254 }
1255}
1256
1257// Auxiliary method to create a [Vec<Range>] from a [cxx::Vector<RangeValueRuleRange>].
1258fn range_values_from_cxx(
1259 range_values_cxx: &cxx::Vector<maliput_sys::api::rules::ffi::RangeValueRuleRange>,
1260) -> Vec<Range> {
1261 range_values_cxx
1262 .iter()
1263 .map(|range| Range {
1264 rule_state: RuleStateBase {
1265 severity: maliput_sys::api::rules::ffi::RangeValueRuleRange_severity(range),
1266 related_rules: maliput_sys::api::rules::ffi::RangeValueRuleRange_related_rules(range),
1267 related_unique_ids: maliput_sys::api::rules::ffi::RangeValueRuleRange_related_unique_ids(range),
1268 },
1269 description: maliput_sys::api::rules::ffi::RangeValueRuleRange_description(range),
1270 min: maliput_sys::api::rules::ffi::RangeValueRuleRange_min(range),
1271 max: maliput_sys::api::rules::ffi::RangeValueRuleRange_max(range),
1272 })
1273 .collect()
1274}
1275
1276// Auxiliary method to create a [Vec<DiscreteValue>] from a [cxx::Vector<DiscreteValueRuleDiscreteValue>].
1277fn discrete_values_from_cxx(
1278 discrete_values_cxx: &cxx::Vector<maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue>,
1279) -> Vec<DiscreteValue> {
1280 discrete_values_cxx
1281 .iter()
1282 .map(discrete_value_from_discrete_value_cxx)
1283 .collect()
1284}
1285
1286// Auxiliary method to create a [DiscreteValue] from a [maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue].
1287fn discrete_value_from_discrete_value_cxx(
1288 discrete_value: &maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue,
1289) -> DiscreteValue {
1290 DiscreteValue {
1291 rule_state: RuleStateBase {
1292 severity: maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue_severity(discrete_value),
1293 related_rules: maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue_related_rules(discrete_value),
1294 related_unique_ids: maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue_related_unique_ids(
1295 discrete_value,
1296 ),
1297 },
1298 value: maliput_sys::api::rules::ffi::DiscreteValueRuleDiscreteValue_value(discrete_value),
1299 }
1300}