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