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