maliput/api/rules/
mod.rs

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