maliput/api/
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::math::Matrix3;
32use crate::math::Quaternion;
33use crate::math::RollPitchYaw;
34use crate::math::Vector3;
35
36pub mod rules;
37
38/// A RoadGeometry.
39/// Wrapper around C++ implementation `maliput::api::RoadGeometry`.
40/// See RoadNetwork for an example of how to get a RoadGeometry.
41pub struct RoadGeometry<'a> {
42    rg: &'a maliput_sys::api::ffi::RoadGeometry,
43}
44
45impl<'a> RoadGeometry<'a> {
46    /// Returns the id of the RoadGeometry.
47    pub fn id(&self) -> String {
48        maliput_sys::api::ffi::RoadGeometry_id(self.rg)
49    }
50    /// Returns the number of Junctions in the RoadGeometry.
51    ///
52    /// Return value is non-negative.
53    pub fn num_junctions(&self) -> i32 {
54        self.rg.num_junctions()
55    }
56    /// Returns the tolerance guaranteed for linear measurements (positions).
57    pub fn linear_tolerance(&self) -> f64 {
58        self.rg.linear_tolerance()
59    }
60    /// Returns the tolerance guaranteed for angular measurements (orientations).
61    pub fn angular_tolerance(&self) -> f64 {
62        self.rg.angular_tolerance()
63    }
64    /// Returns the number of BranchPoints in the RoadGeometry.
65    ///
66    /// Return value is non-negative.
67    pub fn num_branch_points(&self) -> i32 {
68        self.rg.num_branch_points()
69    }
70    /// Determines the RoadPosition corresponding to InertialPosition `inertial_position`.
71    ///
72    /// Returns a RoadPositionResult. Its RoadPosition is the point in the
73    /// RoadGeometry's manifold which is, in the `Inertial`-frame, closest to
74    /// `inertial_position`. Its InertialPosition is the `Inertial`-frame equivalent of the
75    /// RoadPosition and its distance is the Cartesian distance from
76    /// `inertial_position` to the nearest point.
77    ///
78    /// This method guarantees that its result satisfies the condition that
79    /// `result.lane.to_lane_position(result.pos)` is within `linear_tolerance()`
80    /// of the returned InertialPosition.
81    ///
82    /// The map from RoadGeometry to the `Inertial`-frame is not onto (as a bounded
83    /// RoadGeometry cannot completely cover the unbounded Cartesian universe).
84    /// If `inertial_position` does represent a point contained within the volume
85    /// of the RoadGeometry, then result distance is guaranteed to be less
86    /// than or equal to `linear_tolerance()`.
87    ///
88    /// The map from RoadGeometry to `Inertial`-frame is not necessarily one-to-one.
89    /// Different `(s,r,h)` coordinates from different Lanes, potentially from
90    /// different Segments, may map to the same `(x,y,z)` `Inertial`-frame location.
91    ///
92    /// If `inertial_position` is contained within the volumes of multiple Segments,
93    /// then ToRoadPosition() will choose a Segment which yields the minimum
94    /// height `h` value in the result.  If the chosen Segment has multiple
95    /// Lanes, then ToRoadPosition() will choose a Lane which contains
96    /// `inertial_position` within its `lane_bounds()` if possible, and if that is
97    /// still ambiguous, it will further select a Lane which minimizes the
98    /// absolute value of the lateral `r` coordinate in the result.
99    ///
100    /// Wrapper around C++ implementation `maliput::api::RoadGeometry::ToRoadPosition`.
101    pub fn to_road_position(&self, inertial_position: &InertialPosition) -> RoadPositionResult {
102        let rpr = maliput_sys::api::ffi::RoadGeometry_ToRoadPosition(self.rg, &inertial_position.ip);
103        RoadPositionResult {
104            road_position: RoadPosition {
105                rp: maliput_sys::api::ffi::RoadPositionResult_road_position(&rpr),
106            },
107            nearest_position: InertialPosition {
108                ip: maliput_sys::api::ffi::RoadPositionResult_nearest_position(&rpr),
109            },
110            distance: maliput_sys::api::ffi::RoadPositionResult_distance(&rpr),
111        }
112    }
113    /// Get the lane matching given `lane_id`.
114    /// ### Arguments
115    /// * `lane_id` - The id of the lane.
116    /// ### Return
117    /// The lane with the given id.
118    /// If no lane is found with the given id, return None.
119    pub fn get_lane(&self, lane_id: &String) -> Option<Lane> {
120        let lane = maliput_sys::api::ffi::RoadGeometry_GetLane(self.rg, lane_id);
121        if lane.lane.is_null() {
122            return None;
123        }
124        Some(Lane {
125            lane: unsafe { lane.lane.as_ref().expect("") },
126        })
127    }
128    /// Get all lanes of the `RoadGeometry`.
129    /// Returns a vector of `Lane`.
130    /// # Example
131    /// ```rust, no_run
132    /// use maliput::api::RoadNetwork;
133    /// use std::collections::HashMap;
134    ///
135    /// let package_location = std::env::var("CARGO_MANIFEST_DIR").unwrap();
136    /// let xodr_path = format!("{}/data/xodr/TShapeRoad.xodr", package_location);
137    /// let road_network_properties = HashMap::from([("road_geometry_id", "my_rg_from_rust"), ("opendrive_file", xodr_path.as_str())]);
138    /// let road_network = RoadNetwork::new("maliput_malidrive", &road_network_properties);
139    /// let road_geometry = road_network.road_geometry();
140    /// let lanes = road_geometry.get_lanes();
141    /// for lane in lanes {
142    ///    println!("lane_id: {}", lane.id());
143    /// }
144    /// ```
145    pub fn get_lanes(&self) -> Vec<Lane> {
146        let lanes = maliput_sys::api::ffi::RoadGeometry_GetLanes(self.rg);
147        lanes
148            .into_iter()
149            .map(|l| Lane {
150                lane: unsafe { l.lane.as_ref().expect("") },
151            })
152            .collect::<Vec<Lane>>()
153    }
154    /// Get the segment matching given `segment_id`.
155    pub fn get_segment(&self, segment_id: &String) -> Segment {
156        unsafe {
157            Segment {
158                segment: maliput_sys::api::ffi::RoadGeometry_GetSegment(self.rg, segment_id)
159                    .as_ref()
160                    .expect(""),
161            }
162        }
163    }
164    /// Get the junction matching given `junction_id`.
165    pub fn get_junction(&self, junction_id: &String) -> Junction {
166        unsafe {
167            Junction {
168                junction: maliput_sys::api::ffi::RoadGeometry_GetJunction(self.rg, junction_id)
169                    .as_ref()
170                    .expect(""),
171            }
172        }
173    }
174    /// Get the branch point matching given `branch_point_id`.
175    pub fn get_branch_point(&self, branch_point_id: &String) -> BranchPoint {
176        unsafe {
177            BranchPoint {
178                branch_point: maliput_sys::api::ffi::RoadGeometry_GetBranchPoint(self.rg, branch_point_id)
179                    .as_ref()
180                    .expect("Underlying BranchPoint is null"),
181            }
182        }
183    }
184    /// Execute a custom command on the backend.
185    /// ### Details
186    /// The documentation of the custom command should be provided by the backend: https://github.com/maliput/maliput_malidrive/blob/main/src/maliput_malidrive/base/road_geometry.h
187    ///
188    /// ### Arguments
189    /// * `command` - The command to execute.
190    ///
191    /// ### Return
192    /// The result of the command.
193    pub fn backend_custom_command(&self, command: &String) -> String {
194        maliput_sys::api::ffi::RoadGeometry_BackendCustomCommand(self.rg, command)
195    }
196}
197
198/// A RoadNetwork.
199/// Wrapper around C++ implementation `maliput::api::RoadNetwork`.
200///
201/// ## Example
202///
203/// ```rust, no_run
204/// use maliput::api::RoadNetwork;
205/// use std::collections::HashMap;
206///
207/// let package_location = std::env::var("CARGO_MANIFEST_DIR").unwrap();
208/// let xodr_path = format!("{}/data/xodr/TShapeRoad.xodr", package_location);
209/// let road_network_properties = HashMap::from([("road_geometry_id", "my_rg_from_rust"), ("opendrive_file", xodr_path.as_str())]);
210/// let road_network = RoadNetwork::new("maliput_malidrive", &road_network_properties);
211/// let road_geometry = road_network.road_geometry();
212/// println!("num_junctions: {}", road_geometry.num_junctions());
213/// ```
214pub struct RoadNetwork {
215    pub(crate) rn: cxx::UniquePtr<maliput_sys::api::ffi::RoadNetwork>,
216}
217
218impl RoadNetwork {
219    /// Create a new `RoadNetwork` with the given `road_network_loader_id` and `properties`.
220    ///
221    /// # Arguments
222    ///
223    /// * `road_network_loader_id` - The id of the road network loader.
224    /// * `properties` - The properties of the road network.
225    ///
226    /// # Details
227    /// It relies on `maliput_sys::plugin::ffi::CreateRoadNetwork` to create a new `RoadNetwork`.
228    pub fn new(road_network_loader_id: &str, properties: &std::collections::HashMap<&str, &str>) -> RoadNetwork {
229        // Translate the properties to ffi types
230        let mut properties_vec = Vec::new();
231        for (key, value) in properties.iter() {
232            properties_vec.push(format!("{}:{}", key, value));
233        }
234        std::env::set_var("MALIPUT_PLUGIN_PATH", maliput_sdk::get_maliput_malidrive_plugin_path());
235        RoadNetwork {
236            rn: maliput_sys::plugin::ffi::CreateRoadNetwork(&road_network_loader_id.to_string(), &properties_vec),
237        }
238    }
239
240    /// Get the `RoadGeometry` of the `RoadNetwork`.
241    pub fn road_geometry(&self) -> RoadGeometry {
242        unsafe {
243            RoadGeometry {
244                rg: self.rn.road_geometry().as_ref().expect(""),
245            }
246        }
247    }
248    /// Get the `IntersectionBook` of the `RoadNetwork`.
249    pub fn intersection_book(&mut self) -> IntersectionBook {
250        let intersection_book_ffi = self
251            .rn
252            .as_mut()
253            .expect("Underlying RoadNetwork is null")
254            .intersection_book();
255        IntersectionBook {
256            intersection_book: unsafe {
257                intersection_book_ffi
258                    .as_mut()
259                    .expect("Underlying IntersectionBook is null")
260            },
261        }
262    }
263    /// Get the `TrafficLightBook` of the `RoadNetwork`.
264    pub fn traffic_light_book(&self) -> rules::TrafficLightBook {
265        let traffic_light_book_ffi = self.rn.traffic_light_book();
266        rules::TrafficLightBook {
267            traffic_light_book: unsafe {
268                traffic_light_book_ffi
269                    .as_ref()
270                    .expect("Underlying TrafficLightBook is null")
271            },
272        }
273    }
274    /// Get the `RoadRulebook` of the `RoadNetwork`.
275    pub fn rulebook(&self) -> rules::RoadRulebook {
276        let rulebook_ffi = self.rn.rulebook();
277        rules::RoadRulebook {
278            road_rulebook: unsafe { rulebook_ffi.as_ref().expect("Underlying RoadRulebook is null") },
279        }
280    }
281}
282
283/// A Lane Position.
284/// Wrapper around C++ implementation `maliput::api::LanePosition`.
285///
286/// ## Example
287///
288/// ```rust, no_run
289/// use maliput::api::LanePosition;
290///
291/// let lane_pos = LanePosition::new(1.0, 2.0, 3.0);
292/// println!("lane_pos = {}", lane_pos);
293/// assert_eq!(lane_pos.s(), 1.0);
294/// assert_eq!(lane_pos.r(), 2.0);
295/// assert_eq!(lane_pos.h(), 3.0);
296/// ```
297pub struct LanePosition {
298    lp: cxx::UniquePtr<maliput_sys::api::ffi::LanePosition>,
299}
300
301impl LanePosition {
302    /// Create a new `LanePosition` with the given `s`, `r`, and `h` components.
303    pub fn new(s: f64, r: f64, h: f64) -> LanePosition {
304        LanePosition {
305            lp: maliput_sys::api::ffi::LanePosition_new(s, r, h),
306        }
307    }
308    /// Get the `s` component of the `LanePosition`.
309    pub fn s(&self) -> f64 {
310        self.lp.s()
311    }
312    /// Get the `r` component of the `LanePosition`.
313    pub fn r(&self) -> f64 {
314        self.lp.r()
315    }
316    /// Get the `h` component of the `LanePosition`.
317    pub fn h(&self) -> f64 {
318        self.lp.h()
319    }
320
321    /// Returns all components as 3-vector `[s, r, h]`.
322    pub fn srh(&self) -> Vector3 {
323        let srh = self.lp.srh();
324        Vector3::new(srh.x(), srh.y(), srh.z())
325    }
326
327    /// Set the `s` component of the `LanePosition`.
328    pub fn set_s(&mut self, s: f64) {
329        self.lp.as_mut().expect("Underlying LanePosition is null").set_s(s);
330    }
331
332    /// Set the `r` component of the `LanePosition`.
333    pub fn set_r(&mut self, r: f64) {
334        self.lp.as_mut().expect("Underlying LanePosition is null").set_r(r);
335    }
336
337    /// Set the `h` component of the `LanePosition`.
338    pub fn set_h(&mut self, h: f64) {
339        self.lp.as_mut().expect("Underlying LanePosition is null").set_h(h);
340    }
341
342    /// Set all components from 3-vector `[s, r, h]`.
343    pub fn set_srh(&mut self, srh: &Vector3) {
344        let ffi_vec = maliput_sys::math::ffi::Vector3_new(srh.x(), srh.y(), srh.z());
345        self.lp
346            .as_mut()
347            .expect("Underlying LanePosition is null")
348            .set_srh(&ffi_vec);
349    }
350}
351
352impl PartialEq for LanePosition {
353    fn eq(&self, other: &Self) -> bool {
354        self.srh() == other.srh()
355    }
356}
357
358impl Eq for LanePosition {}
359
360impl std::fmt::Display for LanePosition {
361    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
362        write!(f, "{}", maliput_sys::api::ffi::LanePosition_to_str(&self.lp))
363    }
364}
365
366impl std::fmt::Debug for LanePosition {
367    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
368        f.debug_struct("LanePosition")
369            .field("s", &self.s())
370            .field("r", &self.r())
371            .field("h", &self.h())
372            .finish()
373    }
374}
375
376/// An Inertial Position.
377/// Wrapper around C++ implementation `maliput::api::InertialPosition`.
378///
379/// ## Example
380///
381/// ```rust, no_run
382/// use maliput::api::InertialPosition;
383///
384/// let inertial_pos = InertialPosition::new(1.0, 2.0, 3.0);
385/// println!("inertial_pos = {}", inertial_pos);
386/// assert_eq!(inertial_pos.x(), 1.0);
387/// assert_eq!(inertial_pos.y(), 2.0);
388/// assert_eq!(inertial_pos.z(), 3.0);
389/// ```
390pub struct InertialPosition {
391    ip: cxx::UniquePtr<maliput_sys::api::ffi::InertialPosition>,
392}
393
394impl InertialPosition {
395    /// Create a new `InertialPosition` with the given `x`, `y`, and `z` components.
396    pub fn new(x: f64, y: f64, z: f64) -> InertialPosition {
397        InertialPosition {
398            ip: maliput_sys::api::ffi::InertialPosition_new(x, y, z),
399        }
400    }
401    /// Get the `x` component of the `InertialPosition`.
402    pub fn x(&self) -> f64 {
403        self.ip.x()
404    }
405    /// Get the `y` component of the `InertialPosition`.
406    pub fn y(&self) -> f64 {
407        self.ip.y()
408    }
409    /// Get the `z` component of the `InertialPosition`.
410    pub fn z(&self) -> f64 {
411        self.ip.z()
412    }
413
414    /// Returns all components as 3-vector `[x, y, z]`.
415    pub fn xyz(&self) -> Vector3 {
416        let xyz = self.ip.xyz();
417        Vector3::new(xyz.x(), xyz.y(), xyz.z())
418    }
419
420    /// Set the `x` component of the `InertialPosition`.
421    pub fn set_x(&mut self, x: f64) {
422        self.ip.as_mut().expect("Underlying InertialPosition is null").set_x(x);
423    }
424
425    /// Set the `y` component of the `InertialPosition`.
426    pub fn set_y(&mut self, y: f64) {
427        self.ip.as_mut().expect("Underlying InertialPosition is null").set_y(y);
428    }
429
430    /// Set the `z` component of the `InertialPosition`.
431    pub fn set_z(&mut self, z: f64) {
432        self.ip.as_mut().expect("Underlying InertialPosition is null").set_z(z);
433    }
434
435    /// Set all components from 3-vector `[x, y, z]`.
436    pub fn set_xyz(&mut self, xyz: &Vector3) {
437        let ffi_vec = maliput_sys::math::ffi::Vector3_new(xyz.x(), xyz.y(), xyz.z());
438        self.ip
439            .as_mut()
440            .expect("Underlying InertialPosition is null")
441            .set_xyz(&ffi_vec);
442    }
443
444    /// Get the length of `InertialPosition`.
445    pub fn length(&self) -> f64 {
446        self.ip.length()
447    }
448
449    /// Get the distance between two `InertialPosition`.
450    pub fn distance(&self, other: &InertialPosition) -> f64 {
451        self.ip.Distance(&other.ip)
452    }
453}
454
455impl PartialEq for InertialPosition {
456    fn eq(&self, other: &Self) -> bool {
457        maliput_sys::api::ffi::InertialPosition_operator_eq(&self.ip, &other.ip)
458    }
459}
460
461impl Eq for InertialPosition {}
462
463impl std::fmt::Display for InertialPosition {
464    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
465        write!(f, "{}", maliput_sys::api::ffi::InertialPosition_to_str(&self.ip))
466    }
467}
468
469impl std::fmt::Debug for InertialPosition {
470    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
471        f.debug_struct("InertialPosition")
472            .field("x", &self.x())
473            .field("y", &self.y())
474            .field("z", &self.z())
475            .finish()
476    }
477}
478
479impl std::ops::Add for InertialPosition {
480    type Output = InertialPosition;
481
482    fn add(self, other: InertialPosition) -> InertialPosition {
483        InertialPosition {
484            ip: maliput_sys::api::ffi::InertialPosition_operator_sum(&self.ip, &other.ip),
485        }
486    }
487}
488
489impl std::ops::Sub for InertialPosition {
490    type Output = InertialPosition;
491
492    fn sub(self, other: InertialPosition) -> InertialPosition {
493        InertialPosition {
494            ip: maliput_sys::api::ffi::InertialPosition_operator_sub(&self.ip, &other.ip),
495        }
496    }
497}
498
499impl std::ops::Mul<f64> for InertialPosition {
500    type Output = InertialPosition;
501
502    fn mul(self, scalar: f64) -> InertialPosition {
503        InertialPosition {
504            ip: maliput_sys::api::ffi::InertialPosition_operator_mul_scalar(&self.ip, scalar),
505        }
506    }
507}
508
509/// Bounds in the lateral dimension (r component) of a `Lane`-frame, consisting
510/// of a pair of minimum and maximum r value.  The bounds must straddle r = 0,
511/// i.e., the minimum must be <= 0 and the maximum must be >= 0.
512pub struct RBounds {
513    min: f64,
514    max: f64,
515}
516
517impl RBounds {
518    pub fn new(min: f64, max: f64) -> RBounds {
519        RBounds { min, max }
520    }
521    pub fn min(&self) -> f64 {
522        self.min
523    }
524    pub fn max(&self) -> f64 {
525        self.max
526    }
527    pub fn set_min(&mut self, min: f64) {
528        self.min = min;
529    }
530    pub fn set_max(&mut self, max: f64) {
531        self.max = max;
532    }
533}
534
535/// Bounds in the elevation dimension (`h` component) of a `Lane`-frame,
536/// consisting of a pair of minimum and maximum `h` value.  The bounds
537/// must straddle `h = 0`, i.e., the minimum must be `<= 0` and the
538/// maximum must be `>= 0`.
539pub struct HBounds {
540    min: f64,
541    max: f64,
542}
543
544impl HBounds {
545    pub fn new(min: f64, max: f64) -> HBounds {
546        HBounds { min, max }
547    }
548    pub fn min(&self) -> f64 {
549        self.min
550    }
551    pub fn max(&self) -> f64 {
552        self.max
553    }
554    pub fn set_min(&mut self, min: f64) {
555        self.min = min;
556    }
557    pub fn set_max(&mut self, max: f64) {
558        self.max = max;
559    }
560}
561
562/// Isometric velocity vector in a `Lane`-frame.
563///
564/// sigma_v, rho_v, and eta_v are the components of velocity in a
565/// (sigma, rho, eta) coordinate system.  (sigma, rho, eta) have the same
566/// orientation as the (s, r, h) at any given point in space, however they
567/// form an isometric system with a Cartesian distance metric.  Hence,
568/// IsoLaneVelocity represents a "real" physical velocity vector (albeit
569/// with an orientation relative to the road surface).
570#[derive(Default, Copy, Clone, Debug, PartialEq)]
571pub struct IsoLaneVelocity {
572    pub sigma_v: f64,
573    pub rho_v: f64,
574    pub eta_v: f64,
575}
576
577impl IsoLaneVelocity {
578    /// Create a new `IsoLaneVelocity` with the given `sigma_v`, `rho_v`, and `eta_v` components.
579    pub fn new(sigma_v: f64, rho_v: f64, eta_v: f64) -> IsoLaneVelocity {
580        IsoLaneVelocity { sigma_v, rho_v, eta_v }
581    }
582}
583
584/// A maliput::api::Lane
585/// Wrapper around C++ implementation `maliput::api::Lane`.
586pub struct Lane<'a> {
587    lane: &'a maliput_sys::api::ffi::Lane,
588}
589
590impl<'a> Lane<'a> {
591    /// Returns the index of this Lane within the Segment which owns it.
592    pub fn index(&self) -> i32 {
593        self.lane.index()
594    }
595    /// Get the left lane of the `Lane`.
596    pub fn to_left(&self) -> Option<Lane> {
597        let lane = self.lane.to_left();
598        if lane.is_null() {
599            None
600        } else {
601            unsafe {
602                Some(Lane {
603                    lane: lane.as_ref().expect(""),
604                })
605            }
606        }
607    }
608    /// Get the right lane of the `Lane`.
609    pub fn to_right(&self) -> Option<Lane> {
610        let lane = self.lane.to_right();
611        if lane.is_null() {
612            None
613        } else {
614            unsafe {
615                Some(Lane {
616                    lane: lane.as_ref().expect(""),
617                })
618            }
619        }
620    }
621    /// Get the length of the `Lane`.
622    pub fn length(&self) -> f64 {
623        self.lane.length()
624    }
625    /// Get the id of the `Lane` as a string.
626    pub fn id(&self) -> String {
627        maliput_sys::api::ffi::Lane_id(self.lane)
628    }
629    /// Returns the Segment to which this Lane belongs.
630    pub fn segment(&self) -> Segment<'a> {
631        unsafe {
632            Segment {
633                segment: self.lane.segment().as_ref().expect(""),
634            }
635        }
636    }
637    /// Get the orientation of the `Lane` at the given `LanePosition`.
638    pub fn get_orientation(&self, lane_position: &LanePosition) -> Rotation {
639        Rotation {
640            r: maliput_sys::api::ffi::Lane_GetOrientation(self.lane, lane_position.lp.as_ref().expect("")),
641        }
642    }
643    /// Get the inertial position of the `Lane` at the given `LanePosition`.
644    pub fn to_inertial_position(&self, lane_position: &LanePosition) -> InertialPosition {
645        InertialPosition {
646            ip: maliput_sys::api::ffi::Lane_ToInertialPosition(self.lane, lane_position.lp.as_ref().expect("")),
647        }
648    }
649    /// Determines the LanePosition corresponding to InertialPosition `inertial_position`.
650    /// The LanePosition is expected to be contained within the lane's boundaries.
651    /// See [Lane::to_segment_position] method.
652    ///
653    /// This method guarantees that its result satisfies the condition that
654    /// `to_inertial_position(result.lane_position)` is within `linear_tolerance()`
655    ///  of `result.nearest_position`.
656    pub fn to_lane_position(&self, inertial_position: &InertialPosition) -> LanePositionResult {
657        let lpr = maliput_sys::api::ffi::Lane_ToLanePosition(self.lane, inertial_position.ip.as_ref().expect(""));
658        LanePositionResult {
659            lane_position: LanePosition {
660                lp: maliput_sys::api::ffi::LanePositionResult_road_position(&lpr),
661            },
662            nearest_position: InertialPosition {
663                ip: maliput_sys::api::ffi::LanePositionResult_nearest_position(&lpr),
664            },
665            distance: maliput_sys::api::ffi::LanePositionResult_distance(&lpr),
666        }
667    }
668    /// Determines the LanePosition corresponding to InertialPosition `inertial_position`.
669    /// The LanePosition is expected to be contained within the segment's boundaries.
670    /// See [Lane::to_lane_position] method.
671    ///
672    /// This method guarantees that its result satisfies the condition that
673    /// `to_inertial_position(result.lane_position)` is within `linear_tolerance()`
674    ///  of `result.nearest_position`.
675    pub fn to_segment_position(&self, inertial_position: &InertialPosition) -> LanePositionResult {
676        let spr = maliput_sys::api::ffi::Lane_ToSegmentPosition(self.lane, inertial_position.ip.as_ref().expect(""));
677        LanePositionResult {
678            lane_position: LanePosition {
679                lp: maliput_sys::api::ffi::LanePositionResult_road_position(&spr),
680            },
681            nearest_position: InertialPosition {
682                ip: maliput_sys::api::ffi::LanePositionResult_nearest_position(&spr),
683            },
684            distance: maliput_sys::api::ffi::LanePositionResult_distance(&spr),
685        }
686    }
687    /// Get the lane bounds of the `Lane` at the given `s`.
688    pub fn lane_bounds(&self, s: f64) -> RBounds {
689        let bounds = maliput_sys::api::ffi::Lane_lane_bounds(self.lane, s);
690        RBounds::new(bounds.min(), bounds.max())
691    }
692    /// Get the segment bounds of the `Lane` at the given `s`.
693    pub fn segment_bounds(&self, s: f64) -> RBounds {
694        let bounds = maliput_sys::api::ffi::Lane_segment_bounds(self.lane, s);
695        RBounds::new(bounds.min(), bounds.max())
696    }
697    /// Get the elevation bounds of the `Lane` at the given `s` and `r`.
698    pub fn elevation_bounds(&self, s: f64, r: f64) -> HBounds {
699        let bounds = maliput_sys::api::ffi::Lane_elevation_bounds(self.lane, s, r);
700        HBounds::new(bounds.min(), bounds.max())
701    }
702    /// Computes derivatives of [LanePosition] given a velocity vector `velocity`.
703    /// `velocity` is a isometric velocity vector oriented in the `Lane`-frame
704    /// at `position`.
705    ///
706    /// Returns `Lane`-frame derivatives packed into a [LanePosition] struct.
707    pub fn eval_motion_derivatives(&self, lane_position: &LanePosition, velocity: &IsoLaneVelocity) -> LanePosition {
708        LanePosition {
709            lp: maliput_sys::api::ffi::Lane_EvalMotionDerivatives(
710                self.lane,
711                lane_position.lp.as_ref().expect(""),
712                velocity.sigma_v,
713                velocity.rho_v,
714                velocity.eta_v,
715            ),
716        }
717    }
718    /// Returns the lane's BranchPoint for the specified end.
719    pub fn get_branch_point(&self, end: &LaneEnd) -> BranchPoint {
720        assert! {
721            end == &LaneEnd::Start(self.clone()) || end == &LaneEnd::Finish(self.clone()),
722            "LaneEnd must be an end of this lane {:?}",
723            end
724        }
725        BranchPoint {
726            branch_point: unsafe {
727                maliput_sys::api::ffi::Lane_GetBranchPoint(self.lane, end == &LaneEnd::Start(self.clone()))
728                    .as_ref()
729                    .expect("Underlying BranchPoint is null")
730            },
731        }
732    }
733    /// Returns the set of LaneEnd's which connect with this lane on the
734    /// same side of the BranchPoint at `end`. At a minimum,
735    /// this set will include this Lane.
736    pub fn get_confluent_branches(&self, end: &LaneEnd) -> LaneEndSet {
737        assert! {
738            end == &LaneEnd::Start(self.clone()) || end == &LaneEnd::Finish(self.clone()),
739            "LaneEnd must be an end of this lane {:?}",
740            end
741        }
742        LaneEndSet {
743            lane_end_set: unsafe {
744                maliput_sys::api::ffi::Lane_GetConfluentBranches(self.lane, end == &LaneEnd::Start(self.clone()))
745                    .as_ref()
746                    .expect("Underlying LaneEndSet is null")
747            },
748        }
749    }
750    /// Returns the set of LaneEnd's which continue onward from this lane at the
751    /// BranchPoint at `end`.
752    pub fn get_ongoing_branches(&self, end: &LaneEnd) -> LaneEndSet {
753        assert! {
754            end == &LaneEnd::Start(self.clone()) || end == &LaneEnd::Finish(self.clone()),
755            "LaneEnd must be an end of this lane {:?}",
756            end
757        }
758        LaneEndSet {
759            lane_end_set: unsafe {
760                maliput_sys::api::ffi::Lane_GetOngoingBranches(self.lane, end == &LaneEnd::Start(self.clone()))
761                    .as_ref()
762                    .expect("Underlying LaneEndSet is null")
763            },
764        }
765    }
766    /// Returns the default ongoing LaneEnd connected at `end`,
767    /// or None if no default branch has been established.
768    pub fn get_default_branch(&self, end: &LaneEnd) -> Option<LaneEnd> {
769        assert! {
770            end == &LaneEnd::Start(self.clone()) || end == &LaneEnd::Finish(self.clone()),
771            "LaneEnd must be an end of this lane {:?}",
772            end
773        }
774        let lane_end = maliput_sys::api::ffi::Lane_GetDefaultBranch(self.lane, end == &LaneEnd::Start(self.clone()));
775        match lane_end.is_null() {
776            true => None,
777            false => {
778                let lane_end_ref: &maliput_sys::api::ffi::LaneEnd =
779                    lane_end.as_ref().expect("Underlying LaneEnd is null");
780                let is_start = maliput_sys::api::ffi::LaneEnd_is_start(lane_end_ref);
781                let lane_ref = unsafe {
782                    maliput_sys::api::ffi::LaneEnd_lane(lane_end_ref)
783                        .as_ref()
784                        .expect("Underlying LaneEnd is null")
785                };
786                match is_start {
787                    true => Some(LaneEnd::Start(Lane { lane: lane_ref })),
788                    false => Some(LaneEnd::Finish(Lane { lane: lane_ref })),
789                }
790            }
791        }
792    }
793    /// Check if the `Lane` contains the given `LanePosition`.
794    pub fn contains(&self, lane_position: &LanePosition) -> bool {
795        self.lane.Contains(lane_position.lp.as_ref().expect(""))
796    }
797}
798
799/// Copy trait for Lane.
800/// A reference to the Lane is copied.
801impl Clone for Lane<'_> {
802    fn clone(&self) -> Self {
803        Lane { lane: self.lane }
804    }
805}
806
807/// A Segment represents a bundle of adjacent Lanes which share a
808/// continuously traversable road surface. Every [LanePosition] on a
809/// given [Lane] of a Segment has a corresponding [LanePosition] on each
810/// other [Lane], all with the same height-above-surface h, that all
811/// map to the same GeoPoint in 3-space.
812///
813/// Segments are grouped by [Junction].
814///
815/// Wrapper around C++ implementation `maliput::api::Segment`.
816pub struct Segment<'a> {
817    segment: &'a maliput_sys::api::ffi::Segment,
818}
819
820impl<'a> Segment<'a> {
821    /// Get the id of the `Segment` as a string.
822    pub fn id(&self) -> String {
823        maliput_sys::api::ffi::Segment_id(self.segment)
824    }
825    /// Returns the [Junction] to which this Segment belongs.
826    pub fn junction(&self) -> Junction {
827        unsafe {
828            Junction {
829                junction: self.segment.junction().as_ref().expect(""),
830            }
831        }
832    }
833    /// Get the number of lanes in the `Segment`.
834    pub fn num_lanes(&self) -> i32 {
835        self.segment.num_lanes()
836    }
837    /// Get the lane at the given `index`.
838    pub fn lane(&self, index: i32) -> Lane {
839        unsafe {
840            Lane {
841                lane: self.segment.lane(index).as_ref().expect(""),
842            }
843        }
844    }
845}
846
847/// A Junction is a closed set of [Segment]s which have physically
848/// coplanar road surfaces, in the sense that [RoadPosition]s with the
849/// same h value (height above surface) in the domains of two [Segment]s
850/// map to the same [InertialPosition].  The [Segment]s need not be directly
851/// connected to one another in the network topology.
852///
853/// Junctions are grouped by [RoadGeometry].
854///
855/// Wrapper around C++ implementation `maliput::api::Segment`.
856pub struct Junction<'a> {
857    junction: &'a maliput_sys::api::ffi::Junction,
858}
859
860impl<'a> Junction<'a> {
861    /// Get the id of the `Junction` as a string.
862    pub fn id(&self) -> String {
863        maliput_sys::api::ffi::Junction_id(self.junction)
864    }
865    /// Get the road geometry of the `Junction`.
866    pub fn road_geometry(&self) -> RoadGeometry {
867        unsafe {
868            RoadGeometry {
869                rg: self.junction.road_geometry().as_ref().expect(""),
870            }
871        }
872    }
873    /// Get the number of segments in the `Junction`.
874    pub fn num_segments(&self) -> i32 {
875        self.junction.num_segments()
876    }
877    /// Get the segment at the given `index`.
878    pub fn segment(&self, index: i32) -> Segment {
879        unsafe {
880            Segment {
881                segment: self.junction.segment(index).as_ref().expect(""),
882            }
883        }
884    }
885}
886
887/// A maliput::api::RoadPosition
888/// Wrapper around C++ implementation `maliput::api::RoadPosition`.
889pub struct RoadPosition {
890    rp: cxx::UniquePtr<maliput_sys::api::ffi::RoadPosition>,
891}
892
893impl RoadPosition {
894    /// Create a new `RoadPosition` with the given `lane` and `lane_pos`.
895    pub fn new(lane: &Lane, lane_pos: &LanePosition) -> RoadPosition {
896        unsafe {
897            RoadPosition {
898                rp: maliput_sys::api::ffi::RoadPosition_new(lane.lane, &lane_pos.lp),
899            }
900        }
901    }
902    /// Get the inertial position of the `RoadPosition` via doing a Lane::ToInertialPosition query call.
903    pub fn to_inertial_position(&self) -> InertialPosition {
904        InertialPosition {
905            ip: maliput_sys::api::ffi::RoadPosition_ToInertialPosition(&self.rp),
906        }
907    }
908    /// Get the lane of the `RoadPosition`.
909    pub fn lane(&self) -> Lane {
910        unsafe {
911            Lane {
912                lane: maliput_sys::api::ffi::RoadPosition_lane(&self.rp).as_ref().expect(""),
913            }
914        }
915    }
916    /// Get the lane position of the `RoadPosition`.
917    pub fn pos(&self) -> LanePosition {
918        LanePosition {
919            lp: maliput_sys::api::ffi::RoadPosition_pos(&self.rp),
920        }
921    }
922}
923
924/// Represents the result of a RoadPosition query.
925pub struct RoadPositionResult {
926    pub road_position: RoadPosition,
927    pub nearest_position: InertialPosition,
928    pub distance: f64,
929}
930
931impl RoadPositionResult {
932    /// Create a new `RoadPositionResult` with the given `road_position`, `nearest_position`, and `distance`.
933    pub fn new(road_position: RoadPosition, nearest_position: InertialPosition, distance: f64) -> RoadPositionResult {
934        RoadPositionResult {
935            road_position,
936            nearest_position,
937            distance,
938        }
939    }
940}
941
942/// Represents the result of a LanePosition query.
943pub struct LanePositionResult {
944    pub lane_position: LanePosition,
945    pub nearest_position: InertialPosition,
946    pub distance: f64,
947}
948
949impl LanePositionResult {
950    /// Create a new `LanePositionResult` with the given `lane_position`, `nearest_position`, and `distance`.
951    pub fn new(lane_position: LanePosition, nearest_position: InertialPosition, distance: f64) -> LanePositionResult {
952        LanePositionResult {
953            lane_position,
954            nearest_position,
955            distance,
956        }
957    }
958}
959
960/// A maliput::api::Rotation
961/// A wrapper around C++ implementation `maliput::api::Rotation`.
962pub struct Rotation {
963    r: cxx::UniquePtr<maliput_sys::api::ffi::Rotation>,
964}
965
966impl Default for Rotation {
967    fn default() -> Self {
968        Self::new()
969    }
970}
971
972impl Rotation {
973    /// Create a new `Rotation`.
974    pub fn new() -> Rotation {
975        Rotation {
976            r: maliput_sys::api::ffi::Rotation_new(),
977        }
978    }
979    /// Create a new `Rotation` from a `Quaternion`.
980    pub fn from_quat(q: &Quaternion) -> Rotation {
981        let q_ffi = maliput_sys::math::ffi::Quaternion_new(q.w(), q.x(), q.y(), q.z());
982        Rotation {
983            r: maliput_sys::api::ffi::Rotation_from_quat(&q_ffi),
984        }
985    }
986    /// Create a new `Rotation` from a `RollPitchYaw`.
987    pub fn from_rpy(rpy: &RollPitchYaw) -> Rotation {
988        let rpy_ffi = maliput_sys::math::ffi::RollPitchYaw_new(rpy.roll_angle(), rpy.pitch_angle(), rpy.yaw_angle());
989        Rotation {
990            r: maliput_sys::api::ffi::Rotation_from_rpy(&rpy_ffi),
991        }
992    }
993    /// Get the roll of the `Rotation`.
994    pub fn roll(&self) -> f64 {
995        self.r.roll()
996    }
997    /// Get the pitch of the `Rotation`.
998    pub fn pitch(&self) -> f64 {
999        self.r.pitch()
1000    }
1001    /// Get the yaw of the `Rotation`.
1002    pub fn yaw(&self) -> f64 {
1003        self.r.yaw()
1004    }
1005    /// Get a quaternion representation of the `Rotation`.
1006    pub fn quat(&self) -> Quaternion {
1007        let q_ffi = self.r.quat();
1008        Quaternion::new(q_ffi.w(), q_ffi.x(), q_ffi.y(), q_ffi.z())
1009    }
1010    /// Get a roll-pitch-yaw representation of the `Rotation`.
1011    pub fn rpy(&self) -> RollPitchYaw {
1012        let rpy_ffi = maliput_sys::api::ffi::Rotation_rpy(&self.r);
1013        RollPitchYaw::new(rpy_ffi.roll_angle(), rpy_ffi.pitch_angle(), rpy_ffi.yaw_angle())
1014    }
1015    /// Set the `Rotation` from a `Quaternion`.
1016    pub fn set_quat(&mut self, q: &Quaternion) {
1017        let q_ffi = maliput_sys::math::ffi::Quaternion_new(q.w(), q.x(), q.y(), q.z());
1018        maliput_sys::api::ffi::Rotation_set_quat(self.r.pin_mut(), &q_ffi);
1019    }
1020    /// Get the matrix representation of the `Rotation`.
1021    pub fn matrix(&self) -> Matrix3 {
1022        let matrix_ffi: cxx::UniquePtr<maliput_sys::math::ffi::Matrix3> =
1023            maliput_sys::api::ffi::Rotation_matrix(&self.r);
1024        let row_0 = maliput_sys::math::ffi::Matrix3_row(matrix_ffi.as_ref().expect(""), 0);
1025        let row_1 = maliput_sys::math::ffi::Matrix3_row(matrix_ffi.as_ref().expect(""), 1);
1026        let row_2 = maliput_sys::math::ffi::Matrix3_row(matrix_ffi.as_ref().expect(""), 2);
1027        Matrix3::new(
1028            Vector3::new(row_0.x(), row_0.y(), row_0.z()),
1029            Vector3::new(row_1.x(), row_1.y(), row_1.z()),
1030            Vector3::new(row_2.x(), row_2.y(), row_2.z()),
1031        )
1032    }
1033    /// Get the distance between two `Rotation`.
1034    pub fn distance(&self, other: &Rotation) -> f64 {
1035        self.r.Distance(&other.r)
1036    }
1037    /// Apply the `Rotation` to an `InertialPosition`.
1038    pub fn apply(&self, v: &InertialPosition) -> InertialPosition {
1039        InertialPosition {
1040            ip: maliput_sys::api::ffi::Rotation_Apply(&self.r, &v.ip),
1041        }
1042    }
1043    /// Get the reverse of the `Rotation`.
1044    pub fn reverse(&self) -> Rotation {
1045        Rotation {
1046            r: maliput_sys::api::ffi::Rotation_Reverse(&self.r),
1047        }
1048    }
1049}
1050
1051/// Directed, inclusive longitudinal (s value) range from s0 to s1.
1052/// Wrapper around C++ implementation `maliput::api::SRange`.
1053pub struct SRange {
1054    s_range: cxx::UniquePtr<maliput_sys::api::ffi::SRange>,
1055}
1056
1057impl SRange {
1058    /// Create a new `SRange` with the given `s0` and `s1`.
1059    pub fn new(s0: f64, s1: f64) -> SRange {
1060        SRange {
1061            s_range: maliput_sys::api::ffi::SRange_new(s0, s1),
1062        }
1063    }
1064    /// Get the s0 of the `SRange`.
1065    pub fn s0(&self) -> f64 {
1066        self.s_range.s0()
1067    }
1068    /// Get the s1 of the `SRange`.
1069    pub fn s1(&self) -> f64 {
1070        self.s_range.s1()
1071    }
1072    /// Set the s0 of the `SRange`.
1073    pub fn set_s0(&mut self, s0: f64) {
1074        self.s_range.as_mut().expect("Underlying SRange is null").set_s0(s0);
1075    }
1076    /// Set the s1 of the `SRange`.
1077    pub fn set_s1(&mut self, s1: f64) {
1078        self.s_range.as_mut().expect("Underlying SRange is null").set_s1(s1);
1079    }
1080    /// Get the size of the `SRange`.
1081    pub fn size(&self) -> f64 {
1082        self.s_range.size()
1083    }
1084    /// Returns true When this SRange is in the direction of +s.
1085    pub fn with_s(&self) -> bool {
1086        self.s_range.WithS()
1087    }
1088    /// Determines whether this SRange intersects with `s_range`.
1089    pub fn intersects(&self, s_range: &SRange, tolerance: f64) -> bool {
1090        self.s_range.Intersects(&s_range.s_range, tolerance)
1091    }
1092    /// Determines whether this SRange contains `s_range`.
1093    pub fn contains(&self, s_range: &SRange, tolerance: f64) -> bool {
1094        self.s_range.Contains(&s_range.s_range, tolerance)
1095    }
1096    /// Get the intersection of this SRange with `s_range`.
1097    /// Returns None if the intersection is empty.
1098    pub fn get_intersection(&self, s_range: &SRange, tolerance: f64) -> Option<SRange> {
1099        let intersection = maliput_sys::api::ffi::SRange_GetIntersection(&self.s_range, &s_range.s_range, tolerance);
1100        match intersection.is_null() {
1101            true => None,
1102            false => Some(SRange { s_range: intersection }),
1103        }
1104    }
1105}
1106
1107/// Directed longitudinal range of a specific Lane, identified by a LaneId.
1108/// Wrapper around C++ implementation `maliput::api::LaneSRange`.
1109pub struct LaneSRange {
1110    pub(crate) lane_s_range: cxx::UniquePtr<maliput_sys::api::ffi::LaneSRange>,
1111}
1112
1113impl LaneSRange {
1114    /// Create a new `LaneSRange` with the given `lane_id` and `s_range`.
1115    pub fn new(lane_id: &String, s_range: &SRange) -> LaneSRange {
1116        LaneSRange {
1117            lane_s_range: maliput_sys::api::ffi::LaneSRange_new(lane_id, &s_range.s_range),
1118        }
1119    }
1120    /// Get the lane id of the `LaneSRange`.
1121    pub fn lane_id(&self) -> String {
1122        maliput_sys::api::ffi::LaneSRange_lane_id(&self.lane_s_range)
1123    }
1124    /// Get the s range of the `LaneSRange`.
1125    pub fn s_range(&self) -> SRange {
1126        SRange {
1127            s_range: maliput_sys::api::ffi::LaneSRange_s_range(&self.lane_s_range),
1128        }
1129    }
1130    /// Get the length of the `LaneSRange`.
1131    pub fn length(&self) -> f64 {
1132        self.lane_s_range.length()
1133    }
1134    /// Determines whether this LaneSRange intersects with `lane_s_range`.
1135    pub fn intersects(&self, lane_s_range: &LaneSRange, tolerance: f64) -> bool {
1136        self.lane_s_range.Intersects(&lane_s_range.lane_s_range, tolerance)
1137    }
1138    /// Determines whether this LaneSRange contains `lane_s_range`.
1139    pub fn contains(&self, lane_s_range: &LaneSRange, tolerance: f64) -> bool {
1140        self.lane_s_range.Contains(&lane_s_range.lane_s_range, tolerance)
1141    }
1142    /// Get the intersection of this LaneSRange with `lane_s_range`.
1143    pub fn get_intersection(&self, lane_s_range: &LaneSRange, tolerance: f64) -> Option<LaneSRange> {
1144        let intersection = maliput_sys::api::ffi::LaneSRange_GetIntersection(
1145            &self.lane_s_range,
1146            &lane_s_range.lane_s_range,
1147            tolerance,
1148        );
1149        match intersection.is_null() {
1150            true => None,
1151            false => Some(LaneSRange {
1152                lane_s_range: intersection,
1153            }),
1154        }
1155    }
1156}
1157
1158/// A route, possibly spanning multiple (end-to-end) lanes.
1159///
1160/// The sequence of [LaneSRange]s should be contiguous by either presenting
1161/// laterally adjacent [LaneSRange]s, or consecutive [LaneSRange]s. (In other words,
1162/// taken as a Lane-space path with r=0 and h=0, it should present a
1163/// G1-continuous curve.)
1164pub struct LaneSRoute {
1165    lane_s_route: cxx::UniquePtr<maliput_sys::api::ffi::LaneSRoute>,
1166}
1167
1168impl LaneSRoute {
1169    /// Create a new `LaneSRoute` with the given `ranges`.
1170    ///
1171    /// ## Arguments
1172    /// * `ranges` - A vector of [LaneSRange] to create the [LaneSRoute].
1173    pub fn new(ranges: Vec<LaneSRange>) -> LaneSRoute {
1174        let mut lane_s_ranges_cpp = cxx::CxxVector::new();
1175        for range in &ranges {
1176            lane_s_ranges_cpp
1177                .as_mut()
1178                .unwrap()
1179                .push(maliput_sys::api::ffi::ConstLaneSRangeRef {
1180                    lane_s_range: &range.lane_s_range,
1181                });
1182        }
1183        LaneSRoute {
1184            lane_s_route: maliput_sys::api::ffi::LaneSRoute_new(&lane_s_ranges_cpp),
1185        }
1186    }
1187
1188    /// Returns the sequence of [LaneSRange]s.
1189    pub fn ranges(&self) -> Vec<LaneSRange> {
1190        let mut ranges = Vec::new();
1191        let lane_s_ranges = self.lane_s_route.ranges();
1192        for range in lane_s_ranges {
1193            ranges.push(LaneSRange {
1194                lane_s_range: maliput_sys::api::ffi::LaneSRange_new(
1195                    &maliput_sys::api::ffi::LaneSRange_lane_id(range),
1196                    maliput_sys::api::ffi::LaneSRange_s_range(range).as_ref().expect(""),
1197                ),
1198            })
1199        }
1200        ranges
1201    }
1202
1203    /// Computes the accumulated length of all [LaneSRange]s.
1204    pub fn length(&self) -> f64 {
1205        self.lane_s_route.length()
1206    }
1207
1208    /// Determines whether this LaneSRoute intersects with `other`.
1209    ///
1210    /// ## Arguments
1211    /// * `other` - The other LaneSRoute to check for intersection.
1212    /// * `tolerance` - The tolerance to use for intersection checks.
1213    ///
1214    /// ## Returns
1215    /// * `true` if the two LaneSRoute intersect, `false` otherwise.
1216    pub fn intersects(&self, other: &LaneSRoute, tolerance: f64) -> bool {
1217        self.lane_s_route.Intersects(&other.lane_s_route, tolerance)
1218    }
1219}
1220
1221/// A specific endpoint of a specific Lane.
1222/// This is analogous to the C++ maliput::api::LaneEnd implementation.
1223pub enum LaneEnd<'a> {
1224    /// The start of the Lane. ("s == 0")
1225    Start(Lane<'a>),
1226    /// The end of the Lane. ("s == length")
1227    Finish(Lane<'a>),
1228}
1229
1230impl LaneEnd<'_> {
1231    /// Get the Lane of the `LaneEnd`.
1232    pub fn lane(&self) -> &Lane {
1233        match self {
1234            LaneEnd::Start(lane) => lane,
1235            LaneEnd::Finish(lane) => lane,
1236        }
1237    }
1238}
1239
1240impl PartialEq for LaneEnd<'_> {
1241    fn eq(&self, other: &Self) -> bool {
1242        match self {
1243            LaneEnd::Start(lane) => match other {
1244                LaneEnd::Start(other_lane) => lane.id() == other_lane.id(),
1245                _ => false,
1246            },
1247            LaneEnd::Finish(lane) => match other {
1248                LaneEnd::Finish(other_lane) => lane.id() == other_lane.id(),
1249                _ => false,
1250            },
1251        }
1252    }
1253}
1254
1255impl Eq for LaneEnd<'_> {}
1256
1257impl std::fmt::Display for LaneEnd<'_> {
1258    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1259        match self {
1260            LaneEnd::Start(lane) => write!(f, "LaneEnd::Start({})", lane.id()),
1261            LaneEnd::Finish(lane) => write!(f, "LaneEnd::Finish({})", lane.id()),
1262        }
1263    }
1264}
1265
1266impl std::fmt::Debug for LaneEnd<'_> {
1267    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1268        match self {
1269            LaneEnd::Start(lane) => write!(f, "LaneEnd::Start({})", lane.id()),
1270            LaneEnd::Finish(lane) => write!(f, "LaneEnd::Finish({})", lane.id()),
1271        }
1272    }
1273}
1274
1275/// A set of LaneEnds.
1276pub struct LaneEndSet<'a> {
1277    lane_end_set: &'a maliput_sys::api::ffi::LaneEndSet,
1278}
1279
1280impl<'a> LaneEndSet<'a> {
1281    /// Obtain the size of the LaneEndSet.
1282    pub fn size(&self) -> i32 {
1283        self.lane_end_set.size()
1284    }
1285    /// Get the LaneEnd at the given index.
1286    pub fn get(&self, index: i32) -> LaneEnd {
1287        let lane_end = self.lane_end_set.get(index);
1288        // Obtain end type and lane reference.
1289        let is_start = maliput_sys::api::ffi::LaneEnd_is_start(lane_end);
1290        let lane_ref = unsafe {
1291            maliput_sys::api::ffi::LaneEnd_lane(lane_end)
1292                .as_ref()
1293                .expect("Underlying LaneEnd is null")
1294        };
1295        // Create a LaneEnd enum variant.
1296        match is_start {
1297            true => LaneEnd::Start(Lane { lane: lane_ref }),
1298            false => LaneEnd::Finish(Lane { lane: lane_ref }),
1299        }
1300    }
1301}
1302
1303/// A BranchPoint is a node in the network of a RoadGeometry at which
1304/// Lanes connect to one another.  A BranchPoint is a collection of LaneEnds
1305/// specifying the Lanes (and, in particular, which ends of the Lanes) are
1306/// connected at the BranchPoint.
1307///
1308/// LaneEnds participating in a BranchPoint are grouped into two sets,
1309/// arbitrarily named "A-side" and "B-side". LaneEnds on the same "side"
1310/// have coincident into-the-lane tangent vectors, which are anti-parallel
1311/// to those of LaneEnds on the other side.
1312pub struct BranchPoint<'a> {
1313    branch_point: &'a maliput_sys::api::ffi::BranchPoint,
1314}
1315
1316impl<'a> BranchPoint<'a> {
1317    /// Get the id of the `BranchPoint` as a string.
1318    pub fn id(&self) -> String {
1319        maliput_sys::api::ffi::BranchPoint_id(self.branch_point)
1320    }
1321    pub fn road_geometry(&self) -> RoadGeometry {
1322        unsafe {
1323            RoadGeometry {
1324                rg: self.branch_point.road_geometry().as_ref().expect(""),
1325            }
1326        }
1327    }
1328    /// Returns the set of LaneEnds on the same side as the given LaneEnd.
1329    /// E.g: For a T-junction, this would return the set of LaneEnds on the merging side.
1330    pub fn get_confluent_branches(&self, end: &LaneEnd) -> LaneEndSet {
1331        let lane_end_set_ptr = self.branch_point.GetConfluentBranches(
1332            BranchPoint::from_lane_end_to_ffi(end)
1333                .as_ref()
1334                .expect("Underlying LaneEnd is null"),
1335        );
1336        LaneEndSet {
1337            lane_end_set: unsafe { lane_end_set_ptr.as_ref().expect("Underlying LaneEndSet is null") },
1338        }
1339    }
1340    /// Returns the set of LaneEnds on the opposite side as the given LaneEnd.
1341    /// E.g: For a T-junction, this would return the LaneEnds which end flows into the junction.
1342    pub fn get_ongoing_branches(&self, end: &LaneEnd) -> LaneEndSet {
1343        let lane_end_set_ptr = self.branch_point.GetOngoingBranches(
1344            BranchPoint::from_lane_end_to_ffi(end)
1345                .as_ref()
1346                .expect("Underlying LaneEnd is null"),
1347        );
1348        LaneEndSet {
1349            lane_end_set: unsafe { lane_end_set_ptr.as_ref().expect("Underlying LaneEndSet is null") },
1350        }
1351    }
1352    /// Returns the default ongoing branch (if any) for the given `end`.
1353    /// This typically represents what would be considered "continuing
1354    /// through-traffic" from `end` (e.g., as opposed to a branch executing
1355    /// a turn).
1356    ///
1357    /// If `end` has no default-branch at this BranchPoint, the return
1358    /// value will be None.
1359    pub fn get_default_branch(&self, end: &LaneEnd) -> Option<LaneEnd> {
1360        let lane_end = maliput_sys::api::ffi::BranchPoint_GetDefaultBranch(
1361            self.branch_point,
1362            BranchPoint::from_lane_end_to_ffi(end)
1363                .as_ref()
1364                .expect("Underlying LaneEnd is null"),
1365        );
1366        match lane_end.is_null() {
1367            true => None,
1368            false => {
1369                let lane_end_ref: &maliput_sys::api::ffi::LaneEnd =
1370                    lane_end.as_ref().expect("Underlying LaneEnd is null");
1371                let is_start = maliput_sys::api::ffi::LaneEnd_is_start(lane_end_ref);
1372                let lane_ref = unsafe {
1373                    maliput_sys::api::ffi::LaneEnd_lane(lane_end_ref)
1374                        .as_ref()
1375                        .expect("Underlying LaneEnd is null")
1376                };
1377                match is_start {
1378                    true => Some(LaneEnd::Start(Lane { lane: lane_ref })),
1379                    false => Some(LaneEnd::Finish(Lane { lane: lane_ref })),
1380                }
1381            }
1382        }
1383    }
1384    /// Returns the set of LaneEnds grouped together on the "A-side".
1385    pub fn get_a_side(&self) -> LaneEndSet {
1386        let lane_end_set_ptr = self.branch_point.GetASide();
1387        LaneEndSet {
1388            lane_end_set: unsafe { lane_end_set_ptr.as_ref().expect("Underlying LaneEndSet is null") },
1389        }
1390    }
1391    /// Returns the set of LaneEnds grouped together on the "B-side".
1392    pub fn get_b_side(&self) -> LaneEndSet {
1393        let lane_end_set_ptr = self.branch_point.GetBSide();
1394        LaneEndSet {
1395            lane_end_set: unsafe { lane_end_set_ptr.as_ref().expect("Underlying LaneEndSet is null") },
1396        }
1397    }
1398    /// Convert LaneEnd enum to LaneEnd ffi.
1399    fn from_lane_end_to_ffi(end: &LaneEnd) -> cxx::UniquePtr<maliput_sys::api::ffi::LaneEnd> {
1400        match end {
1401            LaneEnd::Start(lane) => unsafe { maliput_sys::api::ffi::LaneEnd_new(lane.lane, true) },
1402            LaneEnd::Finish(lane) => unsafe { maliput_sys::api::ffi::LaneEnd_new(lane.lane, false) },
1403        }
1404    }
1405}
1406
1407/// An abstract convenience class that aggregates information pertaining to an
1408/// intersection. Its primary purpose is to serve as a single source of this
1409/// information and to remove the need for users to query numerous disparate
1410/// data structures and state providers.
1411pub struct Intersection<'a> {
1412    intersection: &'a mut maliput_sys::api::ffi::Intersection,
1413}
1414
1415impl<'a> Intersection<'a> {
1416    /// Get the id of the `Intersection` as a string.
1417    pub fn id(&self) -> String {
1418        maliput_sys::api::ffi::Intersection_id(self.intersection)
1419    }
1420}
1421
1422/// A book of Intersections.
1423pub struct IntersectionBook<'a> {
1424    intersection_book: &'a mut maliput_sys::api::ffi::IntersectionBook,
1425}
1426
1427impl<'a> IntersectionBook<'a> {
1428    /// Gets a list of all Intersections within this book.
1429    pub fn get_intersections(&mut self) -> Vec<Intersection> {
1430        let book_pin = unsafe { std::pin::Pin::new_unchecked(&mut *self.intersection_book) };
1431        let intersections_cpp = maliput_sys::api::ffi::IntersectionBook_GetIntersections(book_pin);
1432        unsafe {
1433            intersections_cpp
1434                .into_iter()
1435                .map(|intersection| Intersection {
1436                    intersection: intersection
1437                        .intersection
1438                        .as_mut()
1439                        .expect("Underlying Intersection is null"),
1440                })
1441                .collect::<Vec<Intersection>>()
1442        }
1443    }
1444
1445    /// Gets the specified Intersection.
1446    ///
1447    /// ## Arguments
1448    ///   * `id` - The id of the Intersection to get.
1449    ///
1450    /// ## Returns
1451    ///   * An `Option<Intersection>`
1452    ///     * Some(Intersection) - The Intersection with the specified id.
1453    ///     * None - If the Intersection with the specified id does not exist.
1454    pub fn get_intersection(&mut self, id: &str) -> Option<Intersection> {
1455        let book_pin = unsafe { std::pin::Pin::new_unchecked(&mut *self.intersection_book) };
1456        let intersection_option = unsafe {
1457            maliput_sys::api::ffi::IntersectionBook_GetIntersection(book_pin, &String::from(id))
1458                .intersection
1459                .as_mut()
1460        };
1461        match &intersection_option {
1462            None => None,
1463            Some(_) => Some(Intersection {
1464                intersection: intersection_option.expect("Underlying Intersection is null"),
1465            }),
1466        }
1467    }
1468}
1469
1470mod tests {
1471    mod lane_position {
1472        #[test]
1473        fn lane_position_new() {
1474            let lane_pos = crate::api::LanePosition::new(1.0, 2.0, 3.0);
1475            assert_eq!(lane_pos.s(), 1.0);
1476            assert_eq!(lane_pos.r(), 2.0);
1477            assert_eq!(lane_pos.h(), 3.0);
1478        }
1479
1480        #[test]
1481        fn equality() {
1482            let v = crate::api::LanePosition::new(1.0, 2.0, 3.0);
1483            let w = crate::api::LanePosition::new(1.0, 2.0, 3.0);
1484            assert_eq!(v, w);
1485            let z = crate::api::LanePosition::new(4.0, 5.0, 6.0);
1486            assert_ne!(v, z);
1487        }
1488
1489        #[test]
1490        fn set_s() {
1491            let mut lane_pos = crate::api::LanePosition::new(1.0, 2.0, 3.0);
1492            lane_pos.set_s(4.0);
1493            assert_eq!(lane_pos.s(), 4.0);
1494        }
1495
1496        #[test]
1497        fn set_r() {
1498            let mut lane_pos = crate::api::LanePosition::new(1.0, 2.0, 3.0);
1499            lane_pos.set_r(4.0);
1500            assert_eq!(lane_pos.r(), 4.0);
1501        }
1502
1503        #[test]
1504        fn set_h() {
1505            let mut lane_pos = crate::api::LanePosition::new(1.0, 2.0, 3.0);
1506            lane_pos.set_h(4.0);
1507            assert_eq!(lane_pos.h(), 4.0);
1508        }
1509
1510        #[test]
1511        fn set_srh() {
1512            use crate::math::Vector3;
1513            let mut lane_pos = crate::api::LanePosition::new(1.0, 2.0, 3.0);
1514            let vector = Vector3::new(4.0, 5.0, 6.0);
1515            lane_pos.set_srh(&vector);
1516            assert_eq!(lane_pos.s(), 4.0);
1517            assert_eq!(lane_pos.r(), 5.0);
1518            assert_eq!(lane_pos.h(), 6.0);
1519        }
1520    }
1521
1522    mod inertial_position {
1523
1524        #[test]
1525        fn inertial_position_new() {
1526            let inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
1527            assert_eq!(inertial_pos.x(), 1.0);
1528            assert_eq!(inertial_pos.y(), 2.0);
1529            assert_eq!(inertial_pos.z(), 3.0);
1530        }
1531
1532        #[test]
1533        fn equality() {
1534            let v = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
1535            let w = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
1536            assert_eq!(v, w);
1537            let z = crate::api::InertialPosition::new(4.0, 5.0, 6.0);
1538            assert_ne!(v, z);
1539        }
1540
1541        #[test]
1542        fn set_x() {
1543            let mut inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
1544            inertial_pos.set_x(4.0);
1545            assert_eq!(inertial_pos.x(), 4.0);
1546        }
1547
1548        #[test]
1549        fn set_y() {
1550            let mut inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
1551            inertial_pos.set_y(4.0);
1552            assert_eq!(inertial_pos.y(), 4.0);
1553        }
1554
1555        #[test]
1556        fn set_z() {
1557            let mut inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
1558            inertial_pos.set_z(4.0);
1559            assert_eq!(inertial_pos.z(), 4.0);
1560        }
1561
1562        #[test]
1563        fn set_xyz() {
1564            use crate::math::Vector3;
1565            let mut inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
1566            let vector = Vector3::new(4.0, 5.0, 6.0);
1567            inertial_pos.set_xyz(&vector);
1568            assert_eq!(inertial_pos.x(), 4.0);
1569            assert_eq!(inertial_pos.y(), 5.0);
1570            assert_eq!(inertial_pos.z(), 6.0);
1571        }
1572
1573        #[test]
1574        fn xyz() {
1575            let inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
1576            assert_eq!(inertial_pos.xyz(), crate::math::Vector3::new(1.0, 2.0, 3.0));
1577        }
1578
1579        #[test]
1580        fn length() {
1581            let inertial_pos = crate::api::InertialPosition::new(3.0, 0.0, 4.0);
1582            assert_eq!(inertial_pos.length(), 5.0);
1583        }
1584
1585        #[test]
1586        fn distance() {
1587            let inertial_pos1 = crate::api::InertialPosition::new(1.0, 1.0, 1.0);
1588            let inertial_pos2 = crate::api::InertialPosition::new(5.0, 1.0, 1.0);
1589            assert_eq!(inertial_pos1.distance(&inertial_pos2), 4.0);
1590        }
1591
1592        #[test]
1593        fn str() {
1594            let inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
1595            assert_eq!(inertial_pos.to_string(), "(x = 1, y = 2, z = 3)");
1596        }
1597
1598        #[test]
1599        fn add_operation() {
1600            let inertial_pos1 = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
1601            let inertial_pos2 = crate::api::InertialPosition::new(4.0, 5.0, 6.0);
1602            let inertial_pos3 = inertial_pos1 + inertial_pos2;
1603            assert_eq!(inertial_pos3.x(), 5.0);
1604            assert_eq!(inertial_pos3.y(), 7.0);
1605            assert_eq!(inertial_pos3.z(), 9.0);
1606        }
1607
1608        #[test]
1609        fn sub_operation() {
1610            let inertial_pos1 = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
1611            let inertial_pos2 = crate::api::InertialPosition::new(4.0, 5.0, 6.0);
1612            let inertial_pos3 = inertial_pos1 - inertial_pos2;
1613            assert_eq!(inertial_pos3.x(), -3.0);
1614            assert_eq!(inertial_pos3.y(), -3.0);
1615            assert_eq!(inertial_pos3.z(), -3.0);
1616        }
1617
1618        #[test]
1619        fn mul_scalar_operation() {
1620            let inertial_pos1 = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
1621            let inertial_pos2 = inertial_pos1 * 2.0;
1622            assert_eq!(inertial_pos2.x(), 2.0);
1623            assert_eq!(inertial_pos2.y(), 4.0);
1624            assert_eq!(inertial_pos2.z(), 6.0);
1625        }
1626    }
1627    mod rotation {
1628        #[test]
1629        fn rotation_new() {
1630            let rotation = crate::api::Rotation::new();
1631            assert_eq!(rotation.roll(), 0.0);
1632            assert_eq!(rotation.pitch(), 0.0);
1633            assert_eq!(rotation.yaw(), 0.0);
1634        }
1635
1636        #[test]
1637        fn from_quat() {
1638            let quat = crate::math::Quaternion::new(1.0, 0.0, 0.0, 0.0);
1639            let rotation = crate::api::Rotation::from_quat(&quat);
1640            assert_eq!(rotation.roll(), 0.0);
1641            assert_eq!(rotation.pitch(), 0.0);
1642            assert_eq!(rotation.yaw(), 0.0);
1643        }
1644
1645        #[test]
1646        fn from_rpy() {
1647            let rpy = crate::math::RollPitchYaw::new(0.0, 0.0, 0.0);
1648            let rotation = crate::api::Rotation::from_rpy(&rpy);
1649            assert_eq!(rotation.roll(), 0.0);
1650            assert_eq!(rotation.pitch(), 0.0);
1651            assert_eq!(rotation.yaw(), 0.0);
1652        }
1653
1654        #[test]
1655        fn set_quat() {
1656            let mut rotation = crate::api::Rotation::new();
1657            let quat = crate::math::Quaternion::new(1.0, 0.0, 0.0, 0.0);
1658            rotation.set_quat(&quat);
1659            assert_eq!(rotation.roll(), 0.0);
1660            assert_eq!(rotation.pitch(), 0.0);
1661            assert_eq!(rotation.yaw(), 0.0);
1662        }
1663
1664        #[test]
1665        fn matrix() {
1666            let rotation = crate::api::Rotation::new();
1667            let matrix = rotation.matrix();
1668            assert_eq!(matrix.row(0), crate::math::Vector3::new(1.0, 0.0, 0.0));
1669            assert_eq!(matrix.row(1), crate::math::Vector3::new(0.0, 1.0, 0.0));
1670            assert_eq!(matrix.row(2), crate::math::Vector3::new(0.0, 0.0, 1.0));
1671        }
1672    }
1673
1674    mod s_range {
1675        #[test]
1676        fn s_range_new() {
1677            let s_range = crate::api::SRange::new(1.0, 2.0);
1678            assert_eq!(s_range.s0(), 1.0);
1679            assert_eq!(s_range.s1(), 2.0);
1680        }
1681        #[test]
1682        fn s_range_api() {
1683            let s_range_1 = crate::api::SRange::new(1.0, 3.0);
1684            let s_range_2 = crate::api::SRange::new(2.0, 4.0);
1685            assert_eq!(s_range_1.size(), 2.0);
1686            assert!(s_range_1.with_s());
1687            assert!(s_range_1.intersects(&s_range_2, 0.0));
1688            assert!(!s_range_1.contains(&s_range_2, 0.0));
1689        }
1690        #[test]
1691        fn s_range_setters() {
1692            let mut s_range = crate::api::SRange::new(0.0, 4.0);
1693            s_range.set_s0(1.0);
1694            s_range.set_s1(3.0);
1695            assert_eq!(s_range.s0(), 1.0);
1696            assert_eq!(s_range.s1(), 3.0);
1697        }
1698        #[test]
1699        fn s_range_get_intersection_with_intersection() {
1700            let s_range_1 = crate::api::SRange::new(1.0, 3.0);
1701            let s_range_2 = crate::api::SRange::new(2.0, 4.0);
1702            let intersection = s_range_1.get_intersection(&s_range_2, 0.0);
1703            assert!(intersection.is_some());
1704            let intersection = intersection.unwrap();
1705            assert_eq!(intersection.s0(), 2.0);
1706            assert_eq!(intersection.s1(), 3.0);
1707        }
1708        #[test]
1709        fn s_range_get_intersection_with_no_intersection() {
1710            let s_range_1 = crate::api::SRange::new(1.0, 2.0);
1711            let s_range_2 = crate::api::SRange::new(3.0, 4.0);
1712            let intersection = s_range_1.get_intersection(&s_range_2, 0.0);
1713            assert!(intersection.is_none());
1714        }
1715    }
1716
1717    mod lane_s_range {
1718        #[test]
1719        fn lane_s_range_new() {
1720            let lane_s_range =
1721                crate::api::LaneSRange::new(&String::from("lane_test"), &crate::api::SRange::new(1.0, 2.0));
1722            assert_eq!(lane_s_range.lane_id(), "lane_test");
1723            assert_eq!(lane_s_range.s_range().s0(), 1.0);
1724            assert_eq!(lane_s_range.s_range().s1(), 2.0);
1725            assert_eq!(lane_s_range.length(), 1.0);
1726        }
1727        #[test]
1728        fn lane_s_range_api() {
1729            let lane_s_range_1 =
1730                crate::api::LaneSRange::new(&String::from("lane_test"), &crate::api::SRange::new(1.0, 2.0));
1731            let lane_s_range_2 =
1732                crate::api::LaneSRange::new(&String::from("lane_test"), &crate::api::SRange::new(2.0, 3.0));
1733            assert!(lane_s_range_1.intersects(&lane_s_range_2, 0.0));
1734            assert!(!lane_s_range_1.contains(&lane_s_range_2, 0.0));
1735        }
1736        #[test]
1737        fn lane_s_range_get_intersection_with_intersection() {
1738            let lane_s_range_1 =
1739                crate::api::LaneSRange::new(&String::from("lane_test"), &crate::api::SRange::new(1.0, 3.0));
1740            let lane_s_range_2 =
1741                crate::api::LaneSRange::new(&String::from("lane_test"), &crate::api::SRange::new(2.0, 4.0));
1742            let intersection = lane_s_range_1.get_intersection(&lane_s_range_2, 0.0);
1743            assert!(intersection.is_some());
1744            let intersection = intersection.unwrap();
1745            assert_eq!(intersection.lane_id(), "lane_test");
1746            assert_eq!(intersection.s_range().s0(), 2.0);
1747            assert_eq!(intersection.s_range().s1(), 3.0);
1748        }
1749        #[test]
1750        fn lane_s_range_get_intersection_with_no_intersection() {
1751            let lane_s_range_1 =
1752                crate::api::LaneSRange::new(&String::from("lane test_1"), &crate::api::SRange::new(1.0, 3.0));
1753            let lane_s_range_2 =
1754                crate::api::LaneSRange::new(&String::from("lane_test_2"), &crate::api::SRange::new(2.0, 4.0));
1755            let intersection = lane_s_range_1.get_intersection(&lane_s_range_2, 0.0);
1756            assert!(intersection.is_none());
1757        }
1758    }
1759
1760    mod lane_s_route {
1761        // Helper function to create a LaneSRoute
1762        // with two LaneSRange.
1763        // ## Arguments
1764        // * `s0_0` - The s0 of the first LaneSRange.
1765        // * `s1_0` - The s1 of the first LaneSRange.
1766        // * `s0_1` - The s0 of the second LaneSRange.
1767        // * `s1_1` - The s1 of the second LaneSRange.
1768        fn _get_lane_s_route(s0_0: f64, s1_0: f64, s0_1: f64, s1_1: f64) -> crate::api::LaneSRoute {
1769            let ranges = vec![
1770                crate::api::LaneSRange::new(&String::from("lane_test_1"), &crate::api::SRange::new(s0_0, s1_0)),
1771                crate::api::LaneSRange::new(&String::from("lane_test_2"), &crate::api::SRange::new(s0_1, s1_1)),
1772            ];
1773            crate::api::LaneSRoute::new(ranges)
1774        }
1775        #[test]
1776        fn lane_s_route_new() {
1777            let lane_s_route = _get_lane_s_route(0., 10., 0., 15.);
1778            assert!(!lane_s_route.lane_s_route.is_null());
1779            let ranges = lane_s_route.ranges();
1780            assert_eq!(ranges.len(), 2);
1781            assert_eq!(ranges[0].lane_id(), "lane_test_1");
1782            assert_eq!(ranges[1].lane_id(), "lane_test_2");
1783        }
1784        #[test]
1785        fn lane_s_route_length() {
1786            let lane_s_route = _get_lane_s_route(0., 10., 0., 15.);
1787            assert_eq!(lane_s_route.length(), 25.0);
1788        }
1789        #[test]
1790        fn lane_s_route_intersects() {
1791            let lane_s_route = _get_lane_s_route(0., 10., 0., 10.);
1792            let lane_s_route_that_intersects = _get_lane_s_route(5., 9., 5., 9.);
1793            let lane_s_route_that_not_intersects = _get_lane_s_route(11., 20., 11., 20.);
1794            assert!(lane_s_route.intersects(&lane_s_route_that_intersects, 0.0));
1795            assert!(!lane_s_route.intersects(&lane_s_route_that_not_intersects, 0.0));
1796        }
1797    }
1798}