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}