Skip to main content

maliput/api/objects/
mod.rs

1// BSD 3-Clause License
2//
3// Copyright (c) 2026, Woven by Toyota.
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are met:
8//
9// * Redistributions of source code must retain the above copyright notice, this
10//   list of conditions and the following disclaimer.
11//
12// * Redistributions in binary form must reproduce the above copyright notice,
13//   this list of conditions and the following disclaimer in the documentation
14//   and/or other materials provided with the distribution.
15//
16// * Neither the name of the copyright holder nor the names of its
17//   contributors may be used to endorse or promote products derived from
18//   this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31use std::collections::HashMap;
32use strum_macros::{Display, EnumString};
33
34#[derive(Debug, Copy, Clone, PartialEq, Eq, EnumString, Display)]
35/// Defines the possible road object types.
36pub enum RoadObjectType {
37    Unknown,
38    Barrier,
39    GuardWall,
40    GuardRail,
41    Building,
42    Gantry,
43    Obstacle,
44    Pole,
45    TrafficIsland,
46    Tree,
47    Vegetation,
48    Pylon,
49    Delineator,
50}
51
52fn road_object_type_from_cpp(obj_type: maliput_sys::api::objects::ffi::RoadObjectType) -> RoadObjectType {
53    match obj_type {
54        maliput_sys::api::objects::ffi::RoadObjectType::kUnknown => RoadObjectType::Unknown,
55        maliput_sys::api::objects::ffi::RoadObjectType::kBarrier => RoadObjectType::Barrier,
56        maliput_sys::api::objects::ffi::RoadObjectType::kGuardWall => RoadObjectType::GuardWall,
57        maliput_sys::api::objects::ffi::RoadObjectType::kGuardRail => RoadObjectType::GuardRail,
58        maliput_sys::api::objects::ffi::RoadObjectType::kBuilding => RoadObjectType::Building,
59        maliput_sys::api::objects::ffi::RoadObjectType::kGantry => RoadObjectType::Gantry,
60        maliput_sys::api::objects::ffi::RoadObjectType::kObstacle => RoadObjectType::Obstacle,
61        maliput_sys::api::objects::ffi::RoadObjectType::kPole => RoadObjectType::Pole,
62        maliput_sys::api::objects::ffi::RoadObjectType::kTrafficIsland => RoadObjectType::TrafficIsland,
63        maliput_sys::api::objects::ffi::RoadObjectType::kTree => RoadObjectType::Tree,
64        maliput_sys::api::objects::ffi::RoadObjectType::kVegetation => RoadObjectType::Vegetation,
65        maliput_sys::api::objects::ffi::RoadObjectType::kPylon => RoadObjectType::Pylon,
66        maliput_sys::api::objects::ffi::RoadObjectType::kDelineator => RoadObjectType::Delineator,
67        _ => RoadObjectType::Unknown,
68    }
69}
70
71fn road_object_type_to_cpp(obj_type: &RoadObjectType) -> maliput_sys::api::objects::ffi::RoadObjectType {
72    match obj_type {
73        RoadObjectType::Unknown => maliput_sys::api::objects::ffi::RoadObjectType::kUnknown,
74        RoadObjectType::Barrier => maliput_sys::api::objects::ffi::RoadObjectType::kBarrier,
75        RoadObjectType::GuardWall => maliput_sys::api::objects::ffi::RoadObjectType::kGuardWall,
76        RoadObjectType::GuardRail => maliput_sys::api::objects::ffi::RoadObjectType::kGuardRail,
77        RoadObjectType::Building => maliput_sys::api::objects::ffi::RoadObjectType::kBuilding,
78        RoadObjectType::Gantry => maliput_sys::api::objects::ffi::RoadObjectType::kGantry,
79        RoadObjectType::Obstacle => maliput_sys::api::objects::ffi::RoadObjectType::kObstacle,
80        RoadObjectType::Pole => maliput_sys::api::objects::ffi::RoadObjectType::kPole,
81        RoadObjectType::TrafficIsland => maliput_sys::api::objects::ffi::RoadObjectType::kTrafficIsland,
82        RoadObjectType::Tree => maliput_sys::api::objects::ffi::RoadObjectType::kTree,
83        RoadObjectType::Vegetation => maliput_sys::api::objects::ffi::RoadObjectType::kVegetation,
84        RoadObjectType::Pylon => maliput_sys::api::objects::ffi::RoadObjectType::kPylon,
85        RoadObjectType::Delineator => maliput_sys::api::objects::ffi::RoadObjectType::kDelineator,
86    }
87}
88
89/// Represents the position of a [RoadObject] in the road network.
90///
91/// Always contains an inertial position. May also contain a lane position
92/// expressed as `(lane_id, s, r, h)`.
93pub struct RoadObjectPosition {
94    pub inertial_position: crate::api::InertialPosition,
95    pub lane_position: Option<(String, f64, f64, f64)>,
96}
97
98/// Represents a single corner point of an [Outline].
99///
100/// `height` is `Some` when the corner has an explicit height attribute, `None` otherwise.
101pub struct OutlineCorner {
102    pub x: f64,
103    pub y: f64,
104    pub z: f64,
105    pub height: Option<f64>,
106}
107
108/// Represents an outline (a polygon) of a [RoadObject].
109pub struct Outline<'a> {
110    pub(crate) outline: &'a maliput_sys::api::objects::ffi::Outline,
111}
112
113impl<'a> Outline<'a> {
114    /// Returns the unique identifier of this outline.
115    pub fn id(&self) -> String {
116        maliput_sys::api::objects::ffi::Outline_id(self.outline)
117    }
118
119    /// Returns whether this outline is closed (first and last corner coincide).
120    pub fn is_closed(&self) -> bool {
121        maliput_sys::api::objects::ffi::Outline_is_closed(self.outline)
122    }
123
124    /// Returns the number of corners in this outline.
125    pub fn num_corners(&self) -> i32 {
126        maliput_sys::api::objects::ffi::Outline_num_corners(self.outline)
127    }
128
129    /// Returns the corners of this outline.
130    pub fn corners(&self) -> Vec<OutlineCorner> {
131        maliput_sys::api::objects::ffi::Outline_corners(self.outline)
132            .into_iter()
133            .map(|c| OutlineCorner {
134                x: c.x,
135                y: c.y,
136                z: c.z,
137                height: if c.has_height { Some(c.height) } else { None },
138            })
139            .collect()
140    }
141}
142
143/// Models a physical road object in the road network.
144///
145/// A `RoadObject` has a type, position, orientation, bounding box, and optional
146/// outlines and properties.
147pub struct RoadObject<'a> {
148    pub(crate) road_object: &'a maliput_sys::api::objects::ffi::RoadObject,
149}
150
151impl<'a> RoadObject<'a> {
152    /// Returns the unique identifier of this road object.
153    pub fn id(&self) -> String {
154        maliput_sys::api::objects::ffi::RoadObject_id(self.road_object)
155    }
156
157    /// Returns the optional human-readable name of this road object.
158    pub fn name(&self) -> Option<String> {
159        let wrapper = maliput_sys::api::objects::ffi::RoadObject_name(self.road_object);
160        if wrapper.is_null() {
161            return None;
162        }
163        Some(wrapper.value.clone())
164    }
165
166    /// Returns the [RoadObjectType] of this road object.
167    pub fn object_type(&self) -> RoadObjectType {
168        let t = maliput_sys::api::objects::ffi::RoadObject_object_type(self.road_object);
169        road_object_type_from_cpp(t)
170    }
171
172    /// Returns the optional subtype string of this road object.
173    pub fn subtype(&self) -> Option<String> {
174        let wrapper = maliput_sys::api::objects::ffi::RoadObject_subtype(self.road_object);
175        if wrapper.is_null() {
176            return None;
177        }
178        Some(wrapper.value.clone())
179    }
180
181    /// Returns the [RoadObjectPosition] of this road object.
182    pub fn position(&self) -> RoadObjectPosition {
183        let inertial_position = maliput_sys::api::objects::ffi::RoadObject_position_inertial(self.road_object);
184        let has_lane = maliput_sys::api::objects::ffi::RoadObject_position_has_lane_position(self.road_object);
185        let lane_position = if has_lane {
186            Some((
187                maliput_sys::api::objects::ffi::RoadObject_position_lane_id(self.road_object),
188                maliput_sys::api::objects::ffi::RoadObject_position_lane_s(self.road_object),
189                maliput_sys::api::objects::ffi::RoadObject_position_lane_r(self.road_object),
190                maliput_sys::api::objects::ffi::RoadObject_position_lane_h(self.road_object),
191            ))
192        } else {
193            None
194        };
195        RoadObjectPosition {
196            inertial_position: crate::api::InertialPosition { ip: inertial_position },
197            lane_position,
198        }
199    }
200
201    /// Returns the orientation of this road object in the inertial frame.
202    pub fn orientation(&self) -> crate::api::Rotation {
203        let rotation = maliput_sys::api::objects::ffi::RoadObject_orientation(self.road_object);
204        crate::api::Rotation { r: rotation }
205    }
206
207    /// Returns the bounding box of this road object.
208    pub fn bounding_box(&self) -> crate::math::BoundingBox {
209        let b = maliput_sys::api::objects::ffi::RoadObject_bounding_box(self.road_object);
210        crate::math::BoundingBox { b }
211    }
212
213    /// Returns whether this road object is dynamic (i.e., may change position or state).
214    pub fn is_dynamic(&self) -> bool {
215        maliput_sys::api::objects::ffi::RoadObject::is_dynamic(self.road_object)
216    }
217
218    /// Returns whether this road object's position can change.
219    pub fn is_movable(&self) -> bool {
220        maliput_sys::api::objects::ffi::RoadObject::is_movable(self.road_object)
221    }
222
223    /// Returns the IDs of lanes related to this road object.
224    pub fn related_lanes(&self) -> Vec<String> {
225        maliput_sys::api::objects::ffi::RoadObject_related_lanes(self.road_object)
226    }
227
228    /// Returns the number of outlines of this road object.
229    pub fn num_outlines(&self) -> i32 {
230        maliput_sys::api::objects::ffi::RoadObject::num_outlines(self.road_object)
231    }
232
233    /// Returns the outlines of this road object.
234    pub fn outlines(&self) -> Vec<Outline<'_>> {
235        maliput_sys::api::objects::ffi::RoadObject_outlines(self.road_object)
236            .into_iter()
237            .map(|ptr| Outline {
238                outline: unsafe { ptr.outline.as_ref().expect("Outline pointer is null") },
239            })
240            .collect()
241    }
242
243    /// Returns the key-value properties of this road object.
244    pub fn properties(&self) -> HashMap<String, String> {
245        maliput_sys::api::objects::ffi::RoadObject_properties(self.road_object)
246            .into_iter()
247            .map(|p| (p.key, p.value))
248            .collect()
249    }
250}
251
252/// Interface for accessing [RoadObject]s in the road network.
253pub struct RoadObjectBook<'a> {
254    pub(super) road_object_book: &'a maliput_sys::api::objects::ffi::RoadObjectBook,
255}
256
257impl<'a> RoadObjectBook<'a> {
258    /// Returns all [RoadObject]s in the book.
259    pub fn road_objects(&self) -> Vec<RoadObject<'_>> {
260        maliput_sys::api::objects::ffi::RoadObjectBook_RoadObjects(self.road_object_book)
261            .into_iter()
262            .map(|ptr| RoadObject {
263                road_object: unsafe { ptr.road_object.as_ref().expect("RoadObject pointer is null") },
264            })
265            .collect()
266    }
267
268    /// Returns the [RoadObject] with the given `id`, or `None` if not found.
269    pub fn get_road_object(&self, id: &String) -> Option<RoadObject<'_>> {
270        let ptr = maliput_sys::api::objects::ffi::RoadObjectBook_GetRoadObject(self.road_object_book, id);
271        if ptr.is_null() {
272            return None;
273        }
274        Some(RoadObject {
275            road_object: unsafe { ptr.as_ref().expect("Unable to get underlying RoadObject pointer") },
276        })
277    }
278
279    /// Returns all [RoadObject]s of the given [RoadObjectType].
280    pub fn find_by_type(&self, obj_type: &RoadObjectType) -> Vec<RoadObject<'_>> {
281        let obj_type_ffi = road_object_type_to_cpp(obj_type);
282        maliput_sys::api::objects::ffi::RoadObjectBook_FindByType(self.road_object_book, obj_type_ffi)
283            .into_iter()
284            .map(|ptr| RoadObject {
285                road_object: unsafe { ptr.road_object.as_ref().expect("RoadObject pointer is null") },
286            })
287            .collect()
288    }
289
290    /// Returns all [RoadObject]s whose `related_lanes()` includes the given lane ID.
291    pub fn find_by_lane(&self, lane_id: &String) -> Vec<RoadObject<'_>> {
292        maliput_sys::api::objects::ffi::RoadObjectBook_FindByLane(self.road_object_book, lane_id)
293            .into_iter()
294            .map(|ptr| RoadObject {
295                road_object: unsafe { ptr.road_object.as_ref().expect("RoadObject pointer is null") },
296            })
297            .collect()
298    }
299
300    /// Returns all [RoadObject]s within `radius` meters of position `(x, y, z)`.
301    pub fn find_in_radius(&self, x: f64, y: f64, z: f64, radius: f64) -> Vec<RoadObject<'_>> {
302        maliput_sys::api::objects::ffi::RoadObjectBook_FindInRadius(self.road_object_book, x, y, z, radius)
303            .into_iter()
304            .map(|ptr| RoadObject {
305                road_object: unsafe { ptr.road_object.as_ref().expect("RoadObject pointer is null") },
306            })
307            .collect()
308    }
309}
310
311/// Domain alias for road marking semantic types.
312pub type RoadMarkingType = crate::api::rules::TrafficControlDeviceType;
313
314#[derive(Debug, Copy, Clone, PartialEq, Eq)]
315/// Unit of a [RoadMarkingValue].
316pub enum RoadMarkingValueUnit {
317    MetersPerSecond,
318    KilometersPerHour,
319    MilesPerHour,
320}
321
322fn road_marking_value_unit_from_cpp(u: maliput_sys::api::objects::ffi::RoadMarkingValueUnit) -> RoadMarkingValueUnit {
323    match u {
324        maliput_sys::api::objects::ffi::RoadMarkingValueUnit::kMetersPerSecond => RoadMarkingValueUnit::MetersPerSecond,
325        maliput_sys::api::objects::ffi::RoadMarkingValueUnit::kKilometersPerHour => {
326            RoadMarkingValueUnit::KilometersPerHour
327        }
328        maliput_sys::api::objects::ffi::RoadMarkingValueUnit::kMilesPerHour => RoadMarkingValueUnit::MilesPerHour,
329        _ => RoadMarkingValueUnit::MetersPerSecond,
330    }
331}
332
333/// Numeric value (with unit) associated with a [RoadMarking] (e.g. a speed limit).
334#[derive(Debug, Copy, Clone, PartialEq)]
335pub struct RoadMarkingValue {
336    pub value: f64,
337    pub unit: RoadMarkingValueUnit,
338}
339
340/// Models a physical road marking (e.g. stop line, crosswalk, arrow) in the road network.
341pub struct RoadMarking<'a> {
342    pub(crate) road_marking: &'a maliput_sys::api::objects::ffi::RoadMarking,
343}
344
345impl<'a> RoadMarking<'a> {
346    /// Returns the unique identifier of this road marking.
347    pub fn id(&self) -> String {
348        maliput_sys::api::objects::ffi::RoadMarking_id(self.road_marking)
349    }
350
351    /// Returns the optional human-readable name of this road marking.
352    pub fn name(&self) -> Option<String> {
353        let wrapper = maliput_sys::api::objects::ffi::RoadMarking_name(self.road_marking);
354        if wrapper.is_null() {
355            return None;
356        }
357        Some(wrapper.value.clone())
358    }
359
360    /// Returns the [RoadMarkingType] of this road marking.
361    pub fn marking_type(&self) -> RoadMarkingType {
362        let t = maliput_sys::api::objects::ffi::RoadMarking_marking_type(self.road_marking);
363        crate::api::rules::traffic_control_device_type_from_cpp(&t)
364    }
365
366    /// Returns the [RoadObjectPosition] of this road marking.
367    pub fn position(&self) -> RoadObjectPosition {
368        let inertial_position = maliput_sys::api::objects::ffi::RoadMarking_position_inertial(self.road_marking);
369        let has_lane = maliput_sys::api::objects::ffi::RoadMarking_position_has_lane_position(self.road_marking);
370        let lane_position = if has_lane {
371            Some((
372                maliput_sys::api::objects::ffi::RoadMarking_position_lane_id(self.road_marking),
373                maliput_sys::api::objects::ffi::RoadMarking_position_lane_s(self.road_marking),
374                maliput_sys::api::objects::ffi::RoadMarking_position_lane_r(self.road_marking),
375                maliput_sys::api::objects::ffi::RoadMarking_position_lane_h(self.road_marking),
376            ))
377        } else {
378            None
379        };
380        RoadObjectPosition {
381            inertial_position: crate::api::InertialPosition { ip: inertial_position },
382            lane_position,
383        }
384    }
385
386    /// Returns the orientation of this road marking in the inertial frame.
387    pub fn orientation(&self) -> crate::api::Rotation {
388        let rotation = maliput_sys::api::objects::ffi::RoadMarking_orientation(self.road_marking);
389        crate::api::Rotation { r: rotation }
390    }
391
392    /// Returns the bounding box of this road marking.
393    pub fn bounding_box(&self) -> crate::math::BoundingBox {
394        let b = maliput_sys::api::objects::ffi::RoadMarking_bounding_box(self.road_marking);
395        crate::math::BoundingBox { b }
396    }
397
398    /// Returns the IDs of lanes related to this road marking.
399    pub fn related_lanes(&self) -> Vec<String> {
400        maliput_sys::api::objects::ffi::RoadMarking_related_lanes(self.road_marking)
401    }
402
403    /// Returns the number of outlines of this road marking.
404    pub fn num_outlines(&self) -> i32 {
405        maliput_sys::api::objects::ffi::RoadMarking::num_outlines(self.road_marking)
406    }
407
408    /// Returns the outlines of this road marking.
409    pub fn outlines(&self) -> Vec<Outline<'_>> {
410        maliput_sys::api::objects::ffi::RoadMarking_outlines(self.road_marking)
411            .into_iter()
412            .map(|ptr| Outline {
413                outline: unsafe { ptr.outline.as_ref().expect("Outline pointer is null") },
414            })
415            .collect()
416    }
417
418    /// Returns the numeric value (with unit) associated with this road marking, if any.
419    pub fn value(&self) -> Option<RoadMarkingValue> {
420        let data = maliput_sys::api::objects::ffi::RoadMarking_value(self.road_marking);
421        if !data.has_value {
422            return None;
423        }
424        Some(RoadMarkingValue {
425            value: data.value,
426            unit: road_marking_value_unit_from_cpp(data.unit),
427        })
428    }
429}
430
431/// Interface for accessing [RoadMarking]s in the road network.
432pub struct RoadMarkingBook<'a> {
433    pub(super) road_marking_book: &'a maliput_sys::api::objects::ffi::RoadMarkingBook,
434}
435
436impl<'a> RoadMarkingBook<'a> {
437    /// Returns all [RoadMarking]s in the book.
438    pub fn road_markings(&self) -> Vec<RoadMarking<'_>> {
439        maliput_sys::api::objects::ffi::RoadMarkingBook_RoadMarkings(self.road_marking_book)
440            .into_iter()
441            .map(|ptr| RoadMarking {
442                road_marking: unsafe { ptr.road_marking.as_ref().expect("RoadMarking pointer is null") },
443            })
444            .collect()
445    }
446
447    /// Returns the [RoadMarking] with the given `id`, or `None` if not found.
448    pub fn get_road_marking(&self, id: &String) -> Option<RoadMarking<'_>> {
449        let ptr = maliput_sys::api::objects::ffi::RoadMarkingBook_GetRoadMarking(self.road_marking_book, id);
450        if ptr.is_null() {
451            return None;
452        }
453        Some(RoadMarking {
454            road_marking: unsafe { ptr.as_ref().expect("Unable to get underlying RoadMarking pointer") },
455        })
456    }
457
458    /// Returns all [RoadMarking]s whose `related_lanes()` includes the given lane ID.
459    pub fn find_by_lane(&self, lane_id: &String) -> Vec<RoadMarking<'_>> {
460        maliput_sys::api::objects::ffi::RoadMarkingBook_FindByLane(self.road_marking_book, lane_id)
461            .into_iter()
462            .map(|ptr| RoadMarking {
463                road_marking: unsafe { ptr.road_marking.as_ref().expect("RoadMarking pointer is null") },
464            })
465            .collect()
466    }
467
468    /// Returns all [RoadMarking]s of the given [RoadMarkingType].
469    pub fn find_by_type(&self, marking_type: &RoadMarkingType) -> Vec<RoadMarking<'_>> {
470        let t_ffi = crate::api::rules::traffic_control_device_type_to_cpp(marking_type);
471        maliput_sys::api::objects::ffi::RoadMarkingBook_FindByType(self.road_marking_book, t_ffi)
472            .into_iter()
473            .map(|ptr| RoadMarking {
474                road_marking: unsafe { ptr.road_marking.as_ref().expect("RoadMarking pointer is null") },
475            })
476            .collect()
477    }
478}