use crate::common::MaliputError;
use crate::math::Matrix3;
use crate::math::Quaternion;
use crate::math::RollPitchYaw;
use crate::math::Vector3;
pub mod rules;
#[derive(Debug, Clone, Copy, PartialEq, Eq, strum_macros::Display, strum_macros::EnumString)]
pub enum RoadNetworkBackend {
#[cfg(feature = "maliput_malidrive")]
#[strum(serialize = "maliput_malidrive")]
MaliputMalidrive,
#[cfg(feature = "maliput_geopackage")]
#[strum(serialize = "maliput_geopackage")]
MaliputGeopackage,
}
pub struct RoadNetwork {
pub(crate) rn: cxx::UniquePtr<maliput_sys::api::ffi::RoadNetwork>,
}
impl RoadNetwork {
#[allow(clippy::vec_init_then_push)]
pub fn new(
backend: RoadNetworkBackend,
properties: &std::collections::HashMap<&str, &str>,
) -> Result<RoadNetwork, MaliputError> {
let mut properties_vec = Vec::new();
for (key, value) in properties.iter() {
properties_vec.push(format!("{}:{}", key, value));
}
let new_path = match std::env::var_os("MALIPUT_PLUGIN_PATH") {
Some(current_path) => {
let mut new_paths = vec![];
#[cfg(feature = "maliput_malidrive")]
new_paths.push(maliput_sdk::get_maliput_malidrive_plugin_path());
#[cfg(feature = "maliput_geopackage")]
new_paths.push(maliput_sdk::get_maliput_geopackage_plugin_path());
new_paths.extend(std::env::split_paths(¤t_path).collect::<Vec<_>>());
std::env::join_paths(new_paths).unwrap()
}
None => {
let mut paths = vec![];
#[cfg(feature = "maliput_malidrive")]
paths.push(maliput_sdk::get_maliput_malidrive_plugin_path());
#[cfg(feature = "maliput_geopackage")]
paths.push(maliput_sdk::get_maliput_geopackage_plugin_path());
std::env::join_paths(paths).unwrap()
}
};
std::env::set_var("MALIPUT_PLUGIN_PATH", new_path);
let rn = maliput_sys::plugin::ffi::CreateRoadNetwork(&backend.to_string(), &properties_vec)?;
Ok(RoadNetwork { rn })
}
pub fn road_geometry(&self) -> RoadGeometry<'_> {
unsafe {
RoadGeometry {
rg: self.rn.road_geometry().as_ref().expect(""),
}
}
}
pub fn intersection_book(&self) -> IntersectionBook<'_> {
let intersection_book_ffi = maliput_sys::api::ffi::RoadNetwork_intersection_book(&self.rn);
IntersectionBook {
intersection_book: unsafe {
intersection_book_ffi
.as_ref()
.expect("Underlying IntersectionBook is null")
},
}
}
pub fn traffic_light_book(&self) -> rules::TrafficLightBook<'_> {
let traffic_light_book_ffi = self.rn.traffic_light_book();
rules::TrafficLightBook {
traffic_light_book: unsafe {
traffic_light_book_ffi
.as_ref()
.expect("Underlying TrafficLightBook is null")
},
}
}
pub fn rulebook(&self) -> rules::RoadRulebook<'_> {
let rulebook_ffi = self.rn.rulebook();
rules::RoadRulebook {
road_rulebook: unsafe { rulebook_ffi.as_ref().expect("Underlying RoadRulebook is null") },
}
}
pub fn phase_ring_book(&self) -> rules::PhaseRingBook<'_> {
let phase_ring_book_ffi = self.rn.phase_ring_book();
rules::PhaseRingBook {
phase_ring_book: unsafe { phase_ring_book_ffi.as_ref().expect("Underlying PhaseRingBook is null") },
}
}
pub fn rule_registry(&self) -> rules::RuleRegistry<'_> {
let rule_registry_ffi = self.rn.rule_registry();
rules::RuleRegistry {
rule_registry: unsafe { rule_registry_ffi.as_ref().expect("Underlying RuleRegistry is null") },
}
}
pub fn phase_provider(&self) -> rules::PhaseProvider<'_> {
let phase_provider_ffi = maliput_sys::api::ffi::RoadNetwork_phase_provider(&self.rn);
rules::PhaseProvider {
phase_provider: unsafe { phase_provider_ffi.as_ref().expect("Underlying PhaseProvider is null") },
}
}
pub fn discrete_value_rule_state_provider(&self) -> rules::DiscreteValueRuleStateProvider<'_> {
let state_provider = maliput_sys::api::ffi::RoadNetwork_discrete_value_rule_state_provider(&self.rn);
rules::DiscreteValueRuleStateProvider {
state_provider: unsafe {
state_provider
.as_ref()
.expect("Underlying DiscreteValueRuleStateProvider is null")
},
}
}
pub fn range_value_rule_state_provider(&self) -> rules::RangeValueRuleStateProvider<'_> {
let state_provider = maliput_sys::api::ffi::RoadNetwork_range_value_rule_state_provider(&self.rn);
rules::RangeValueRuleStateProvider {
state_provider: unsafe {
state_provider
.as_ref()
.expect("Underlying RangeValueRuleStateProvider is null")
},
}
}
}
pub struct RoadGeometry<'a> {
rg: &'a maliput_sys::api::ffi::RoadGeometry,
}
impl<'a> RoadGeometry<'a> {
pub fn id(&self) -> String {
maliput_sys::api::ffi::RoadGeometry_id(self.rg)
}
pub fn num_junctions(&self) -> i32 {
self.rg.num_junctions()
}
pub fn linear_tolerance(&self) -> f64 {
self.rg.linear_tolerance()
}
pub fn angular_tolerance(&self) -> f64 {
self.rg.angular_tolerance()
}
pub fn num_branch_points(&self) -> i32 {
self.rg.num_branch_points()
}
pub fn to_road_position(&self, inertial_position: &InertialPosition) -> Result<RoadPositionQuery, MaliputError> {
let rpr = maliput_sys::api::ffi::RoadGeometry_ToRoadPosition(self.rg, &inertial_position.ip)?;
Ok(RoadPositionQuery {
road_position: RoadPosition {
rp: maliput_sys::api::ffi::RoadPositionResult_road_position(&rpr),
},
nearest_position: InertialPosition {
ip: maliput_sys::api::ffi::RoadPositionResult_nearest_position(&rpr),
},
distance: maliput_sys::api::ffi::RoadPositionResult_distance(&rpr),
})
}
pub fn to_road_position_surface(&self, inertial_position: &InertialPosition) -> Result<RoadPosition, MaliputError> {
let rpr = maliput_sys::api::ffi::RoadGeometry_ToRoadPosition(self.rg, &inertial_position.ip)?;
let road_position = RoadPosition {
rp: maliput_sys::api::ffi::RoadPositionResult_road_position(&rpr),
};
let distance = maliput_sys::api::ffi::RoadPositionResult_distance(&rpr);
if distance > self.linear_tolerance() {
return Err(MaliputError::Other(format!(
"InertialPosition {} does not correspond to a RoadPosition. It is off by {}m to the closest lane {} at {}.",
maliput_sys::api::ffi::InertialPosition_to_str(&inertial_position.ip),
distance, road_position.lane().id(), road_position.pos())));
}
let lane_position =
maliput_sys::api::ffi::LanePosition_new(road_position.pos().s(), road_position.pos().r(), 0.);
unsafe {
Ok(RoadPosition {
rp: maliput_sys::api::ffi::RoadPosition_new(road_position.lane().lane, &lane_position),
})
}
}
pub fn find_road_positions(
&self,
inertial_position: &InertialPosition,
radius: f64,
) -> Result<Vec<RoadPositionQuery>, MaliputError> {
let positions = maliput_sys::api::ffi::RoadGeometry_FindRoadPositions(self.rg, &inertial_position.ip, radius)?;
Ok(positions
.iter()
.map(|rpr| RoadPositionQuery {
road_position: RoadPosition {
rp: maliput_sys::api::ffi::RoadPositionResult_road_position(rpr),
},
nearest_position: InertialPosition {
ip: maliput_sys::api::ffi::RoadPositionResult_nearest_position(rpr),
},
distance: maliput_sys::api::ffi::RoadPositionResult_distance(rpr),
})
.collect())
}
pub fn find_surface_road_positions_at_xy(
&self,
x: f64,
y: f64,
radius: f64,
) -> Result<Vec<RoadPositionQuery>, MaliputError> {
let positions = maliput_sys::api::ffi::RoadGeometry_FindSurfaceRoadPositionsAtXY(self.rg, x, y, radius)?;
Ok(positions
.iter()
.map(|rpr| RoadPositionQuery {
road_position: RoadPosition {
rp: maliput_sys::api::ffi::RoadPositionResult_road_position(rpr),
},
nearest_position: InertialPosition {
ip: maliput_sys::api::ffi::RoadPositionResult_nearest_position(rpr),
},
distance: maliput_sys::api::ffi::RoadPositionResult_distance(rpr),
})
.collect())
}
pub fn get_lane(&self, lane_id: &String) -> Option<Lane<'_>> {
let lane = maliput_sys::api::ffi::RoadGeometry_GetLane(self.rg, lane_id);
if lane.lane.is_null() {
return None;
}
Some(Lane {
lane: unsafe { lane.lane.as_ref().expect("") },
})
}
pub fn get_lanes(&self) -> Vec<Lane<'_>> {
let lanes = maliput_sys::api::ffi::RoadGeometry_GetLanes(self.rg);
lanes
.into_iter()
.map(|l| Lane {
lane: unsafe { l.lane.as_ref().expect("") },
})
.collect::<Vec<Lane>>()
}
pub fn get_segment(&self, segment_id: &String) -> Option<Segment<'_>> {
let segment = maliput_sys::api::ffi::RoadGeometry_GetSegment(self.rg, segment_id);
if segment.is_null() {
return None;
}
unsafe {
Some(Segment {
segment: segment.as_ref().expect(""),
})
}
}
pub fn get_juntions(&self) -> Result<Vec<Junction<'_>>, MaliputError> {
let mut junctions = vec![];
for i in 0..self.num_junctions() {
if let Some(junction) = self.junction(i) {
junctions.push(junction);
} else {
return Err(MaliputError::Other(format!("No junction found at index {}", i)));
};
}
Ok(junctions)
}
pub fn junction(&self, index: i32) -> Option<Junction<'_>> {
let junction = self.rg.junction(index).ok()?;
if junction.is_null() {
return None;
}
unsafe {
Some(Junction {
junction: junction.as_ref().expect(""),
})
}
}
pub fn get_junction(&self, junction_id: &String) -> Option<Junction<'_>> {
let junction = maliput_sys::api::ffi::RoadGeometry_GetJunction(self.rg, junction_id);
if junction.is_null() {
return None;
}
unsafe {
Some(Junction {
junction: junction.as_ref().expect(""),
})
}
}
pub fn get_branch_point(&self, branch_point_id: &String) -> Option<BranchPoint<'_>> {
let branch_point = maliput_sys::api::ffi::RoadGeometry_GetBranchPoint(self.rg, branch_point_id);
if branch_point.is_null() {
return None;
}
unsafe {
Some(BranchPoint {
branch_point: branch_point.as_ref().expect(""),
})
}
}
pub fn backend_custom_command(&self, command: &String) -> Result<String, MaliputError> {
Ok(maliput_sys::api::ffi::RoadGeometry_BackendCustomCommand(
self.rg, command,
)?)
}
pub fn geo_reference_info(&self) -> String {
maliput_sys::api::ffi::RoadGeometry_GeoReferenceInfo(self.rg)
}
pub fn get_boundary(&self, boundary_id: &String) -> Option<LaneBoundary<'_>> {
let boundary = maliput_sys::api::ffi::RoadGeometry_GetLaneBoundary(self.rg, boundary_id);
if boundary.is_null() {
return None;
}
Some(LaneBoundary {
lane_boundary: unsafe { boundary.as_ref().expect("") },
})
}
}
pub struct LanePosition {
lp: cxx::UniquePtr<maliput_sys::api::ffi::LanePosition>,
}
impl LanePosition {
pub fn new(s: f64, r: f64, h: f64) -> LanePosition {
LanePosition {
lp: maliput_sys::api::ffi::LanePosition_new(s, r, h),
}
}
pub fn s(&self) -> f64 {
self.lp.s()
}
pub fn r(&self) -> f64 {
self.lp.r()
}
pub fn h(&self) -> f64 {
self.lp.h()
}
pub fn srh(&self) -> Vector3 {
let srh = self.lp.srh();
Vector3::new(srh.x(), srh.y(), srh.z())
}
pub fn set_s(&mut self, s: f64) {
self.lp.as_mut().expect("Underlying LanePosition is null").set_s(s);
}
pub fn set_r(&mut self, r: f64) {
self.lp.as_mut().expect("Underlying LanePosition is null").set_r(r);
}
pub fn set_h(&mut self, h: f64) {
self.lp.as_mut().expect("Underlying LanePosition is null").set_h(h);
}
pub fn set_srh(&mut self, srh: &Vector3) {
let ffi_vec = maliput_sys::math::ffi::Vector3_new(srh.x(), srh.y(), srh.z());
self.lp
.as_mut()
.expect("Underlying LanePosition is null")
.set_srh(&ffi_vec);
}
}
impl PartialEq for LanePosition {
fn eq(&self, other: &Self) -> bool {
self.srh() == other.srh()
}
}
impl Eq for LanePosition {}
impl std::fmt::Display for LanePosition {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", maliput_sys::api::ffi::LanePosition_to_str(&self.lp))
}
}
impl std::fmt::Debug for LanePosition {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("LanePosition")
.field("s", &self.s())
.field("r", &self.r())
.field("h", &self.h())
.finish()
}
}
pub struct InertialPosition {
ip: cxx::UniquePtr<maliput_sys::api::ffi::InertialPosition>,
}
impl InertialPosition {
pub fn new(x: f64, y: f64, z: f64) -> InertialPosition {
InertialPosition {
ip: maliput_sys::api::ffi::InertialPosition_new(x, y, z),
}
}
pub fn x(&self) -> f64 {
self.ip.x()
}
pub fn y(&self) -> f64 {
self.ip.y()
}
pub fn z(&self) -> f64 {
self.ip.z()
}
pub fn xyz(&self) -> Vector3 {
let xyz = self.ip.xyz();
Vector3::new(xyz.x(), xyz.y(), xyz.z())
}
pub fn set_x(&mut self, x: f64) {
self.ip.as_mut().expect("Underlying InertialPosition is null").set_x(x);
}
pub fn set_y(&mut self, y: f64) {
self.ip.as_mut().expect("Underlying InertialPosition is null").set_y(y);
}
pub fn set_z(&mut self, z: f64) {
self.ip.as_mut().expect("Underlying InertialPosition is null").set_z(z);
}
pub fn set_xyz(&mut self, xyz: &Vector3) {
let ffi_vec = maliput_sys::math::ffi::Vector3_new(xyz.x(), xyz.y(), xyz.z());
self.ip
.as_mut()
.expect("Underlying InertialPosition is null")
.set_xyz(&ffi_vec);
}
pub fn length(&self) -> f64 {
self.ip.length()
}
pub fn distance(&self, other: &InertialPosition) -> f64 {
self.ip.Distance(&other.ip)
}
}
impl PartialEq for InertialPosition {
fn eq(&self, other: &Self) -> bool {
maliput_sys::api::ffi::InertialPosition_operator_eq(&self.ip, &other.ip)
}
}
impl Eq for InertialPosition {}
impl std::fmt::Display for InertialPosition {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", maliput_sys::api::ffi::InertialPosition_to_str(&self.ip))
}
}
impl std::fmt::Debug for InertialPosition {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("InertialPosition")
.field("x", &self.x())
.field("y", &self.y())
.field("z", &self.z())
.finish()
}
}
impl std::ops::Add for InertialPosition {
type Output = InertialPosition;
fn add(self, other: InertialPosition) -> InertialPosition {
InertialPosition {
ip: maliput_sys::api::ffi::InertialPosition_operator_sum(&self.ip, &other.ip),
}
}
}
impl std::ops::Sub for InertialPosition {
type Output = InertialPosition;
fn sub(self, other: InertialPosition) -> InertialPosition {
InertialPosition {
ip: maliput_sys::api::ffi::InertialPosition_operator_sub(&self.ip, &other.ip),
}
}
}
impl std::ops::Mul<f64> for InertialPosition {
type Output = InertialPosition;
fn mul(self, scalar: f64) -> InertialPosition {
InertialPosition {
ip: maliput_sys::api::ffi::InertialPosition_operator_mul_scalar(&self.ip, scalar),
}
}
}
impl Clone for InertialPosition {
fn clone(&self) -> Self {
InertialPosition {
ip: maliput_sys::api::ffi::InertialPosition_new(self.x(), self.y(), self.z()),
}
}
}
pub struct RBounds {
min: f64,
max: f64,
}
impl RBounds {
pub fn new(min: f64, max: f64) -> RBounds {
RBounds { min, max }
}
pub fn min(&self) -> f64 {
self.min
}
pub fn max(&self) -> f64 {
self.max
}
pub fn set_min(&mut self, min: f64) {
self.min = min;
}
pub fn set_max(&mut self, max: f64) {
self.max = max;
}
}
pub struct HBounds {
min: f64,
max: f64,
}
impl HBounds {
pub fn new(min: f64, max: f64) -> HBounds {
HBounds { min, max }
}
pub fn min(&self) -> f64 {
self.min
}
pub fn max(&self) -> f64 {
self.max
}
pub fn set_min(&mut self, min: f64) {
self.min = min;
}
pub fn set_max(&mut self, max: f64) {
self.max = max;
}
}
#[derive(Default, Copy, Clone, Debug, PartialEq)]
pub struct IsoLaneVelocity {
pub sigma_v: f64,
pub rho_v: f64,
pub eta_v: f64,
}
impl IsoLaneVelocity {
pub fn new(sigma_v: f64, rho_v: f64, eta_v: f64) -> IsoLaneVelocity {
IsoLaneVelocity { sigma_v, rho_v, eta_v }
}
}
#[derive(strum_macros::Display, Debug, Copy, Clone, PartialEq, Eq)]
pub enum LaneType {
Unknown,
Driving,
Turn,
Hov,
Bus,
Taxi,
Emergency,
Shoulder,
Biking,
Walking,
Parking,
Stop,
Border,
Curb,
Median,
Restricted,
Construction,
Rail,
Entry,
Exit,
OnRamp,
OffRamp,
ConnectingRamp,
SlipLane,
Virtual,
}
pub struct Lane<'a> {
lane: &'a maliput_sys::api::ffi::Lane,
}
impl<'a> Lane<'a> {
pub fn id(&self) -> String {
maliput_sys::api::ffi::Lane_id(self.lane)
}
pub fn index(&self) -> i32 {
self.lane.index()
}
pub fn segment(&self) -> Segment<'a> {
unsafe {
Segment {
segment: self.lane.segment().as_ref().expect(""),
}
}
}
pub fn to_left(&self) -> Option<Lane<'_>> {
let lane = self.lane.to_left();
if lane.is_null() {
None
} else {
unsafe {
Some(Lane {
lane: lane.as_ref().expect(""),
})
}
}
}
pub fn to_right(&self) -> Option<Lane<'_>> {
let lane = self.lane.to_right();
if lane.is_null() {
None
} else {
unsafe {
Some(Lane {
lane: lane.as_ref().expect(""),
})
}
}
}
pub fn length(&self) -> f64 {
self.lane.length()
}
pub fn get_orientation(&self, lane_position: &LanePosition) -> Result<Rotation, MaliputError> {
Ok(Rotation {
r: maliput_sys::api::ffi::Lane_GetOrientation(self.lane, lane_position.lp.as_ref().expect(""))?,
})
}
pub fn get_curvature(&self, lane_position: &LanePosition) -> Result<f64, MaliputError> {
Ok(self.lane.GetCurvature(lane_position.lp.as_ref().expect(""))?)
}
pub fn to_inertial_position(&self, lane_position: &LanePosition) -> Result<InertialPosition, MaliputError> {
Ok(InertialPosition {
ip: maliput_sys::api::ffi::Lane_ToInertialPosition(self.lane, lane_position.lp.as_ref().expect(""))?,
})
}
pub fn to_lane_position(&self, inertial_position: &InertialPosition) -> Result<LanePositionQuery, MaliputError> {
let lpr = maliput_sys::api::ffi::Lane_ToLanePosition(self.lane, inertial_position.ip.as_ref().expect(""))?;
Ok(LanePositionQuery {
lane_position: LanePosition {
lp: maliput_sys::api::ffi::LanePositionResult_road_position(&lpr),
},
nearest_position: InertialPosition {
ip: maliput_sys::api::ffi::LanePositionResult_nearest_position(&lpr),
},
distance: maliput_sys::api::ffi::LanePositionResult_distance(&lpr),
})
}
pub fn to_segment_position(&self, inertial_position: &InertialPosition) -> Result<LanePositionQuery, MaliputError> {
let spr = maliput_sys::api::ffi::Lane_ToSegmentPosition(self.lane, inertial_position.ip.as_ref().expect(""))?;
Ok(LanePositionQuery {
lane_position: LanePosition {
lp: maliput_sys::api::ffi::LanePositionResult_road_position(&spr),
},
nearest_position: InertialPosition {
ip: maliput_sys::api::ffi::LanePositionResult_nearest_position(&spr),
},
distance: maliput_sys::api::ffi::LanePositionResult_distance(&spr),
})
}
pub fn lane_bounds(&self, s: f64) -> Result<RBounds, MaliputError> {
let bounds = maliput_sys::api::ffi::Lane_lane_bounds(self.lane, s)?;
Ok(RBounds::new(bounds.min(), bounds.max()))
}
pub fn segment_bounds(&self, s: f64) -> Result<RBounds, MaliputError> {
let bounds = maliput_sys::api::ffi::Lane_segment_bounds(self.lane, s)?;
Ok(RBounds::new(bounds.min(), bounds.max()))
}
pub fn elevation_bounds(&self, s: f64, r: f64) -> Result<HBounds, MaliputError> {
let bounds = maliput_sys::api::ffi::Lane_elevation_bounds(self.lane, s, r)?;
Ok(HBounds::new(bounds.min(), bounds.max()))
}
pub fn eval_motion_derivatives(&self, lane_position: &LanePosition, velocity: &IsoLaneVelocity) -> LanePosition {
LanePosition {
lp: maliput_sys::api::ffi::Lane_EvalMotionDerivatives(
self.lane,
lane_position.lp.as_ref().expect(""),
velocity.sigma_v,
velocity.rho_v,
velocity.eta_v,
),
}
}
pub fn get_branch_point(&self, end: &LaneEnd) -> Result<BranchPoint<'_>, MaliputError> {
if end != &LaneEnd::Start(self.clone()) && end != &LaneEnd::Finish(self.clone()) {
return Err(MaliputError::AssertionError(format!(
"LaneEnd must be an end of this lane {:?}",
end
)));
}
Ok(BranchPoint {
branch_point: unsafe {
maliput_sys::api::ffi::Lane_GetBranchPoint(self.lane, end == &LaneEnd::Start(self.clone()))
.as_ref()
.expect("Underlying BranchPoint is null")
},
})
}
pub fn get_confluent_branches(&self, end: &LaneEnd) -> Result<LaneEndSet<'_>, MaliputError> {
if end != &LaneEnd::Start(self.clone()) && end != &LaneEnd::Finish(self.clone()) {
return Err(MaliputError::AssertionError(format!(
"LaneEnd must be an end of this lane {:?}",
end
)));
}
Ok(LaneEndSet {
lane_end_set: unsafe {
maliput_sys::api::ffi::Lane_GetConfluentBranches(self.lane, end == &LaneEnd::Start(self.clone()))?
.as_ref()
.expect("Underlying LaneEndSet is null")
},
})
}
pub fn get_ongoing_branches(&self, end: &LaneEnd) -> Result<LaneEndSet<'_>, MaliputError> {
if end != &LaneEnd::Start(self.clone()) && end != &LaneEnd::Finish(self.clone()) {
return Err(MaliputError::AssertionError(format!(
"LaneEnd must be an end of this lane {:?}",
end
)));
}
Ok(LaneEndSet {
lane_end_set: unsafe {
maliput_sys::api::ffi::Lane_GetOngoingBranches(self.lane, end == &LaneEnd::Start(self.clone()))?
.as_ref()
.expect("Underlying LaneEndSet is null")
},
})
}
pub fn get_default_branch(&self, end: &LaneEnd) -> Option<LaneEnd<'_>> {
assert! {
end == &LaneEnd::Start(self.clone()) || end == &LaneEnd::Finish(self.clone()),
"LaneEnd must be an end of this lane {:?}",
end
}
let lane_end = maliput_sys::api::ffi::Lane_GetDefaultBranch(self.lane, end == &LaneEnd::Start(self.clone()));
match lane_end.is_null() {
true => None,
false => {
let lane_end_ref: &maliput_sys::api::ffi::LaneEnd =
lane_end.as_ref().expect("Underlying LaneEnd is null");
let is_start = maliput_sys::api::ffi::LaneEnd_is_start(lane_end_ref);
let lane_ref = unsafe {
maliput_sys::api::ffi::LaneEnd_lane(lane_end_ref)
.as_ref()
.expect("Underlying LaneEnd is null")
};
match is_start {
true => Some(LaneEnd::Start(Lane { lane: lane_ref })),
false => Some(LaneEnd::Finish(Lane { lane: lane_ref })),
}
}
}
}
pub fn contains(&self, lane_position: &LanePosition) -> bool {
self.lane.Contains(lane_position.lp.as_ref().expect(""))
}
pub fn lane_type(&self) -> LaneType {
let lane_type = maliput_sys::api::ffi::Lane_type(self.lane);
match lane_type {
maliput_sys::api::ffi::LaneType::kDriving => LaneType::Driving,
maliput_sys::api::ffi::LaneType::kTurn => LaneType::Turn,
maliput_sys::api::ffi::LaneType::kHov => LaneType::Hov,
maliput_sys::api::ffi::LaneType::kBus => LaneType::Bus,
maliput_sys::api::ffi::LaneType::kTaxi => LaneType::Taxi,
maliput_sys::api::ffi::LaneType::kEmergency => LaneType::Emergency,
maliput_sys::api::ffi::LaneType::kShoulder => LaneType::Shoulder,
maliput_sys::api::ffi::LaneType::kBiking => LaneType::Biking,
maliput_sys::api::ffi::LaneType::kWalking => LaneType::Walking,
maliput_sys::api::ffi::LaneType::kParking => LaneType::Parking,
maliput_sys::api::ffi::LaneType::kStop => LaneType::Stop,
maliput_sys::api::ffi::LaneType::kBorder => LaneType::Border,
maliput_sys::api::ffi::LaneType::kCurb => LaneType::Curb,
maliput_sys::api::ffi::LaneType::kMedian => LaneType::Median,
maliput_sys::api::ffi::LaneType::kRestricted => LaneType::Restricted,
maliput_sys::api::ffi::LaneType::kConstruction => LaneType::Construction,
maliput_sys::api::ffi::LaneType::kRail => LaneType::Rail,
maliput_sys::api::ffi::LaneType::kEntry => LaneType::Entry,
maliput_sys::api::ffi::LaneType::kExit => LaneType::Exit,
maliput_sys::api::ffi::LaneType::kOnRamp => LaneType::OnRamp,
maliput_sys::api::ffi::LaneType::kOffRamp => LaneType::OffRamp,
maliput_sys::api::ffi::LaneType::kConnectingRamp => LaneType::ConnectingRamp,
maliput_sys::api::ffi::LaneType::kSlipLane => LaneType::SlipLane,
maliput_sys::api::ffi::LaneType::kVirtual => LaneType::Virtual,
_ => LaneType::Unknown,
}
}
pub fn left_boundary(&self) -> Result<LaneBoundary<'_>, MaliputError> {
let lane_boundary = self.lane.left_boundary()?;
if lane_boundary.is_null() {
return Err(MaliputError::AssertionError(
"Lane does not have a left boundary".to_string(),
));
}
Ok(LaneBoundary {
lane_boundary: unsafe { lane_boundary.as_ref().expect("") },
})
}
pub fn right_boundary(&self) -> Result<LaneBoundary<'_>, MaliputError> {
let lane_boundary = self.lane.right_boundary()?;
if lane_boundary.is_null() {
return Err(MaliputError::AssertionError(
"Lane does not have a right boundary".to_string(),
));
}
Ok(LaneBoundary {
lane_boundary: unsafe { lane_boundary.as_ref().expect("") },
})
}
}
impl Clone for Lane<'_> {
fn clone(&self) -> Self {
Lane { lane: self.lane }
}
}
pub struct Segment<'a> {
segment: &'a maliput_sys::api::ffi::Segment,
}
impl<'a> Segment<'a> {
pub fn id(&self) -> String {
maliput_sys::api::ffi::Segment_id(self.segment)
}
pub fn junction(&self) -> Result<Junction<'_>, MaliputError> {
let junction = self.segment.junction()?;
if junction.is_null() {
return Err(MaliputError::AssertionError(
"Segment does not belong to a Junction".to_string(),
));
}
unsafe {
Ok(Junction {
junction: junction.as_ref().expect(""),
})
}
}
pub fn num_lanes(&self) -> i32 {
self.segment.num_lanes()
}
pub fn lane(&self, index: i32) -> Result<Lane<'_>, MaliputError> {
if index < 0 || index >= self.num_lanes() {
return Err(MaliputError::AssertionError(format!(
"Index {} is out of bounds for Segment with {} lanes",
index,
self.num_lanes()
)));
}
let lane = self.segment.lane(index)?;
unsafe {
Ok(Lane {
lane: lane.as_ref().expect(""),
})
}
}
pub fn num_boundaries(&self) -> i32 {
self.segment.num_boundaries()
}
pub fn boundaries(&self) -> Result<Vec<LaneBoundary<'_>>, MaliputError> {
let mut boundaries = vec![];
for i in 0..self.num_boundaries() {
let boundary = self.boundary(i)?;
boundaries.push(boundary);
}
Ok(boundaries)
}
pub fn boundary(&self, index: i32) -> Result<LaneBoundary<'_>, MaliputError> {
let lane_boundary = self.segment.boundary(index)?;
if lane_boundary.is_null() {
return Err(MaliputError::AssertionError(
"Segment does not have a boundary".to_string(),
));
}
Ok(LaneBoundary {
lane_boundary: unsafe { lane_boundary.as_ref().expect("") },
})
}
}
pub struct Junction<'a> {
junction: &'a maliput_sys::api::ffi::Junction,
}
impl<'a> Junction<'a> {
pub fn id(&self) -> String {
maliput_sys::api::ffi::Junction_id(self.junction)
}
pub fn road_geometry(&self) -> RoadGeometry<'_> {
unsafe {
RoadGeometry {
rg: self.junction.road_geometry().as_ref().expect(""),
}
}
}
pub fn num_segments(&self) -> i32 {
self.junction.num_segments()
}
pub fn segment(&self, index: i32) -> Result<Segment<'_>, MaliputError> {
unsafe {
Ok(Segment {
segment: self.junction.segment(index)?.as_ref().expect(""),
})
}
}
pub fn get_segments(&self) -> Result<Vec<Segment<'_>>, MaliputError> {
let mut segments = vec![];
for i in 0..self.num_segments() {
let segment = self.segment(i)?;
segments.push(segment);
}
Ok(segments)
}
}
pub struct RoadPosition {
rp: cxx::UniquePtr<maliput_sys::api::ffi::RoadPosition>,
}
impl RoadPosition {
pub fn new(lane: &Lane, lane_pos: &LanePosition) -> RoadPosition {
unsafe {
RoadPosition {
rp: maliput_sys::api::ffi::RoadPosition_new(lane.lane, &lane_pos.lp),
}
}
}
pub fn to_inertial_position(&self) -> Result<InertialPosition, MaliputError> {
Ok(InertialPosition {
ip: maliput_sys::api::ffi::RoadPosition_ToInertialPosition(&self.rp)?,
})
}
pub fn lane(&self) -> Lane<'_> {
unsafe {
Lane {
lane: maliput_sys::api::ffi::RoadPosition_lane(&self.rp).as_ref().expect(""),
}
}
}
pub fn pos(&self) -> LanePosition {
LanePosition {
lp: maliput_sys::api::ffi::RoadPosition_pos(&self.rp),
}
}
}
pub struct RoadPositionQuery {
pub road_position: RoadPosition,
pub nearest_position: InertialPosition,
pub distance: f64,
}
impl RoadPositionQuery {
pub fn new(road_position: RoadPosition, nearest_position: InertialPosition, distance: f64) -> RoadPositionQuery {
RoadPositionQuery {
road_position,
nearest_position,
distance,
}
}
}
pub struct LanePositionQuery {
pub lane_position: LanePosition,
pub nearest_position: InertialPosition,
pub distance: f64,
}
impl LanePositionQuery {
pub fn new(lane_position: LanePosition, nearest_position: InertialPosition, distance: f64) -> LanePositionQuery {
LanePositionQuery {
lane_position,
nearest_position,
distance,
}
}
}
pub struct Rotation {
r: cxx::UniquePtr<maliput_sys::api::ffi::Rotation>,
}
impl Default for Rotation {
fn default() -> Self {
Self::new()
}
}
impl Rotation {
pub fn new() -> Rotation {
Rotation {
r: maliput_sys::api::ffi::Rotation_new(),
}
}
pub fn from_quat(q: &Quaternion) -> Rotation {
let q_ffi = maliput_sys::math::ffi::Quaternion_new(q.w(), q.x(), q.y(), q.z());
Rotation {
r: maliput_sys::api::ffi::Rotation_from_quat(&q_ffi),
}
}
pub fn from_rpy(rpy: &RollPitchYaw) -> Rotation {
let rpy_ffi = maliput_sys::math::ffi::RollPitchYaw_new(rpy.roll_angle(), rpy.pitch_angle(), rpy.yaw_angle());
Rotation {
r: maliput_sys::api::ffi::Rotation_from_rpy(&rpy_ffi),
}
}
pub fn roll(&self) -> f64 {
self.r.roll()
}
pub fn pitch(&self) -> f64 {
self.r.pitch()
}
pub fn yaw(&self) -> f64 {
self.r.yaw()
}
pub fn quat(&self) -> Quaternion {
let q_ffi = self.r.quat();
Quaternion::new(q_ffi.w(), q_ffi.x(), q_ffi.y(), q_ffi.z())
}
pub fn rpy(&self) -> RollPitchYaw {
let rpy_ffi = maliput_sys::api::ffi::Rotation_rpy(&self.r);
RollPitchYaw::new(rpy_ffi.roll_angle(), rpy_ffi.pitch_angle(), rpy_ffi.yaw_angle())
}
pub fn set_quat(&mut self, q: &Quaternion) {
let q_ffi = maliput_sys::math::ffi::Quaternion_new(q.w(), q.x(), q.y(), q.z());
maliput_sys::api::ffi::Rotation_set_quat(self.r.pin_mut(), &q_ffi);
}
pub fn matrix(&self) -> Matrix3 {
let matrix_ffi: cxx::UniquePtr<maliput_sys::math::ffi::Matrix3> =
maliput_sys::api::ffi::Rotation_matrix(&self.r);
let row_0 = maliput_sys::math::ffi::Matrix3_row(matrix_ffi.as_ref().expect(""), 0);
let row_1 = maliput_sys::math::ffi::Matrix3_row(matrix_ffi.as_ref().expect(""), 1);
let row_2 = maliput_sys::math::ffi::Matrix3_row(matrix_ffi.as_ref().expect(""), 2);
Matrix3::new(
Vector3::new(row_0.x(), row_0.y(), row_0.z()),
Vector3::new(row_1.x(), row_1.y(), row_1.z()),
Vector3::new(row_2.x(), row_2.y(), row_2.z()),
)
}
pub fn distance(&self, other: &Rotation) -> f64 {
self.r.Distance(&other.r)
}
pub fn apply(&self, v: &InertialPosition) -> InertialPosition {
InertialPosition {
ip: maliput_sys::api::ffi::Rotation_Apply(&self.r, &v.ip),
}
}
pub fn reverse(&self) -> Rotation {
Rotation {
r: maliput_sys::api::ffi::Rotation_Reverse(&self.r),
}
}
}
pub struct SRange {
s_range: cxx::UniquePtr<maliput_sys::api::ffi::SRange>,
}
impl SRange {
pub fn new(s0: f64, s1: f64) -> SRange {
SRange {
s_range: maliput_sys::api::ffi::SRange_new(s0, s1),
}
}
pub fn s0(&self) -> f64 {
self.s_range.s0()
}
pub fn s1(&self) -> f64 {
self.s_range.s1()
}
pub fn set_s0(&mut self, s0: f64) {
self.s_range.as_mut().expect("Underlying SRange is null").set_s0(s0);
}
pub fn set_s1(&mut self, s1: f64) {
self.s_range.as_mut().expect("Underlying SRange is null").set_s1(s1);
}
pub fn size(&self) -> f64 {
self.s_range.size()
}
pub fn with_s(&self) -> bool {
self.s_range.WithS()
}
pub fn intersects(&self, s_range: &SRange, tolerance: f64) -> bool {
self.s_range.Intersects(&s_range.s_range, tolerance)
}
pub fn contains(&self, s_range: &SRange, tolerance: f64) -> bool {
self.s_range.Contains(&s_range.s_range, tolerance)
}
pub fn get_intersection(&self, s_range: &SRange, tolerance: f64) -> Option<SRange> {
let intersection = maliput_sys::api::ffi::SRange_GetIntersection(&self.s_range, &s_range.s_range, tolerance);
match intersection.is_null() {
true => None,
false => Some(SRange { s_range: intersection }),
}
}
}
impl std::fmt::Debug for SRange {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "SRange {{ s0: {}, s1: {} }}", self.s0(), self.s1())
}
}
pub struct LaneSRange {
pub(crate) lane_s_range: cxx::UniquePtr<maliput_sys::api::ffi::LaneSRange>,
}
impl LaneSRange {
pub fn new(lane_id: &String, s_range: &SRange) -> LaneSRange {
LaneSRange {
lane_s_range: maliput_sys::api::ffi::LaneSRange_new(lane_id, &s_range.s_range),
}
}
pub fn lane_id(&self) -> String {
maliput_sys::api::ffi::LaneSRange_lane_id(&self.lane_s_range)
}
pub fn s_range(&self) -> SRange {
SRange {
s_range: maliput_sys::api::ffi::LaneSRange_s_range(&self.lane_s_range),
}
}
pub fn length(&self) -> f64 {
self.lane_s_range.length()
}
pub fn intersects(&self, lane_s_range: &LaneSRange, tolerance: f64) -> bool {
self.lane_s_range.Intersects(&lane_s_range.lane_s_range, tolerance)
}
pub fn contains(&self, lane_s_range: &LaneSRange, tolerance: f64) -> bool {
self.lane_s_range.Contains(&lane_s_range.lane_s_range, tolerance)
}
pub fn get_intersection(&self, lane_s_range: &LaneSRange, tolerance: f64) -> Option<LaneSRange> {
let intersection = maliput_sys::api::ffi::LaneSRange_GetIntersection(
&self.lane_s_range,
&lane_s_range.lane_s_range,
tolerance,
);
match intersection.is_null() {
true => None,
false => Some(LaneSRange {
lane_s_range: intersection,
}),
}
}
}
impl std::fmt::Debug for LaneSRange {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"LaneSRange {{ lane_id: {}, s_range: {:?} }}",
self.lane_id(),
self.s_range()
)
}
}
pub struct LaneSRoute {
lane_s_route: cxx::UniquePtr<maliput_sys::api::ffi::LaneSRoute>,
}
impl LaneSRoute {
pub fn new(ranges: Vec<LaneSRange>) -> LaneSRoute {
let mut lane_s_ranges_cpp = cxx::CxxVector::new();
for range in &ranges {
lane_s_ranges_cpp
.as_mut()
.unwrap()
.push(maliput_sys::api::ffi::ConstLaneSRangeRef {
lane_s_range: &range.lane_s_range,
});
}
LaneSRoute {
lane_s_route: maliput_sys::api::ffi::LaneSRoute_new(&lane_s_ranges_cpp),
}
}
pub fn ranges(&self) -> Vec<LaneSRange> {
let mut ranges = Vec::new();
let lane_s_ranges = self.lane_s_route.ranges();
for range in lane_s_ranges {
ranges.push(LaneSRange {
lane_s_range: maliput_sys::api::ffi::LaneSRange_new(
&maliput_sys::api::ffi::LaneSRange_lane_id(range),
maliput_sys::api::ffi::LaneSRange_s_range(range).as_ref().expect(""),
),
})
}
ranges
}
pub fn length(&self) -> f64 {
self.lane_s_route.length()
}
pub fn intersects(&self, other: &LaneSRoute, tolerance: f64) -> bool {
self.lane_s_route.Intersects(&other.lane_s_route, tolerance)
}
}
impl std::fmt::Debug for LaneSRoute {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "LaneSRoute {{ ranges: {:?} }}", self.ranges())
}
}
pub enum LaneEnd<'a> {
Start(Lane<'a>),
Finish(Lane<'a>),
}
impl LaneEnd<'_> {
pub fn lane(&self) -> &Lane<'_> {
match self {
LaneEnd::Start(lane) => lane,
LaneEnd::Finish(lane) => lane,
}
}
}
impl PartialEq for LaneEnd<'_> {
fn eq(&self, other: &Self) -> bool {
match self {
LaneEnd::Start(lane) => match other {
LaneEnd::Start(other_lane) => lane.id() == other_lane.id(),
_ => false,
},
LaneEnd::Finish(lane) => match other {
LaneEnd::Finish(other_lane) => lane.id() == other_lane.id(),
_ => false,
},
}
}
}
impl Eq for LaneEnd<'_> {}
impl std::fmt::Display for LaneEnd<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
LaneEnd::Start(lane) => write!(f, "LaneEnd::Start({})", lane.id()),
LaneEnd::Finish(lane) => write!(f, "LaneEnd::Finish({})", lane.id()),
}
}
}
impl std::fmt::Debug for LaneEnd<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
LaneEnd::Start(lane) => write!(f, "LaneEnd::Start({})", lane.id()),
LaneEnd::Finish(lane) => write!(f, "LaneEnd::Finish({})", lane.id()),
}
}
}
pub struct LaneEndSet<'a> {
lane_end_set: &'a maliput_sys::api::ffi::LaneEndSet,
}
impl<'a> LaneEndSet<'a> {
pub fn size(&self) -> i32 {
self.lane_end_set.size()
}
pub fn get(&self, index: i32) -> Result<LaneEnd<'_>, MaliputError> {
let lane_end = self.lane_end_set.get(index)?;
let is_start = maliput_sys::api::ffi::LaneEnd_is_start(lane_end);
let lane_ref = unsafe {
maliput_sys::api::ffi::LaneEnd_lane(lane_end)
.as_ref()
.expect("Underlying LaneEnd is null")
};
Ok(match is_start {
true => LaneEnd::Start(Lane { lane: lane_ref }),
false => LaneEnd::Finish(Lane { lane: lane_ref }),
})
}
pub fn to_lane_map(&self) -> std::collections::HashMap<String, LaneEnd<'_>> {
(0..self.size())
.map(|i| {
let end = self.get(i).unwrap();
(end.lane().id(), end)
})
.collect()
}
}
pub struct BranchPoint<'a> {
branch_point: &'a maliput_sys::api::ffi::BranchPoint,
}
impl<'a> BranchPoint<'a> {
pub fn id(&self) -> String {
maliput_sys::api::ffi::BranchPoint_id(self.branch_point)
}
pub fn road_geometry(&self) -> RoadGeometry<'_> {
unsafe {
RoadGeometry {
rg: self.branch_point.road_geometry().as_ref().expect(""),
}
}
}
pub fn get_confluent_branches(&self, end: &LaneEnd) -> Result<LaneEndSet<'_>, MaliputError> {
let lane_end_set_ptr = self.branch_point.GetConfluentBranches(
BranchPoint::from_lane_end_to_ffi(end)
.as_ref()
.expect("Underlying LaneEnd is null"),
)?;
Ok(LaneEndSet {
lane_end_set: unsafe { lane_end_set_ptr.as_ref().expect("Underlying LaneEndSet is null") },
})
}
pub fn get_ongoing_branches(&self, end: &LaneEnd) -> Result<LaneEndSet<'_>, MaliputError> {
let lane_end_set_ptr = self.branch_point.GetOngoingBranches(
BranchPoint::from_lane_end_to_ffi(end)
.as_ref()
.expect("Underlying LaneEnd is null"),
)?;
Ok(LaneEndSet {
lane_end_set: unsafe { lane_end_set_ptr.as_ref().expect("Underlying LaneEndSet is null") },
})
}
pub fn get_default_branch(&self, end: &LaneEnd) -> Option<LaneEnd<'_>> {
let lane_end = maliput_sys::api::ffi::BranchPoint_GetDefaultBranch(
self.branch_point,
BranchPoint::from_lane_end_to_ffi(end)
.as_ref()
.expect("Underlying LaneEnd is null"),
);
match lane_end.is_null() {
true => None,
false => {
let lane_end_ref: &maliput_sys::api::ffi::LaneEnd =
lane_end.as_ref().expect("Underlying LaneEnd is null");
let is_start = maliput_sys::api::ffi::LaneEnd_is_start(lane_end_ref);
let lane_ref = unsafe {
maliput_sys::api::ffi::LaneEnd_lane(lane_end_ref)
.as_ref()
.expect("Underlying LaneEnd is null")
};
match is_start {
true => Some(LaneEnd::Start(Lane { lane: lane_ref })),
false => Some(LaneEnd::Finish(Lane { lane: lane_ref })),
}
}
}
}
pub fn get_a_side(&self) -> LaneEndSet<'_> {
let lane_end_set_ptr = self.branch_point.GetASide();
LaneEndSet {
lane_end_set: unsafe { lane_end_set_ptr.as_ref().expect("Underlying LaneEndSet is null") },
}
}
pub fn get_b_side(&self) -> LaneEndSet<'_> {
let lane_end_set_ptr = self.branch_point.GetBSide();
LaneEndSet {
lane_end_set: unsafe { lane_end_set_ptr.as_ref().expect("Underlying LaneEndSet is null") },
}
}
fn from_lane_end_to_ffi(end: &LaneEnd) -> cxx::UniquePtr<maliput_sys::api::ffi::LaneEnd> {
match end {
LaneEnd::Start(lane) => unsafe { maliput_sys::api::ffi::LaneEnd_new(lane.lane, true) },
LaneEnd::Finish(lane) => unsafe { maliput_sys::api::ffi::LaneEnd_new(lane.lane, false) },
}
}
}
pub struct Intersection<'a> {
intersection: &'a maliput_sys::api::ffi::Intersection,
}
impl<'a> Intersection<'a> {
pub fn id(&self) -> String {
maliput_sys::api::ffi::Intersection_id(self.intersection)
}
pub fn phase(&self) -> rules::StateProviderQuery<String> {
let query = maliput_sys::api::ffi::Intersection_Phase(self.intersection);
let next_state = maliput_sys::api::rules::ffi::PhaseStateProvider_next(&query);
let next_state = if next_state.is_null() {
None
} else {
Some(rules::NextState {
next_state: next_state.phase_id.clone(),
duration_until: if next_state.duration_until.is_null() {
None
} else {
Some(next_state.duration_until.value)
},
})
};
rules::StateProviderQuery {
state: maliput_sys::api::rules::ffi::PhaseStateProvider_state(&query),
next: next_state,
}
}
pub fn region(&self) -> Vec<LaneSRange> {
self.intersection
.region()
.iter()
.map(|region| LaneSRange {
lane_s_range: maliput_sys::api::ffi::LaneSRange_new(
&maliput_sys::api::ffi::LaneSRange_lane_id(region),
&maliput_sys::api::ffi::LaneSRange_s_range(region),
),
})
.collect::<Vec<LaneSRange>>()
}
pub fn phase_ring_id(&self) -> String {
maliput_sys::api::ffi::Intersection_ring_id(self.intersection)
}
pub fn bulb_ids(&self) -> Vec<rules::UniqueBulbId> {
maliput_sys::api::ffi::Intersection_unique_bulb_ids(self.intersection)
.iter()
.map(|unique_bulb_id| rules::UniqueBulbId {
unique_bulb_id: maliput_sys::api::rules::ffi::UniqueBulbId_create_unique_ptr(unique_bulb_id),
})
.collect()
}
pub fn get_bulb_state(&self, unique_bulb_id: &rules::UniqueBulbId) -> Option<rules::BulbState> {
let bulb_state =
maliput_sys::api::ffi::Intersection_bulb_state(self.intersection, &unique_bulb_id.unique_bulb_id);
if bulb_state.is_null() {
return None;
}
match *bulb_state {
maliput_sys::api::ffi::BulbState::kOn => Some(rules::BulbState::On),
maliput_sys::api::ffi::BulbState::kOff => Some(rules::BulbState::Off),
maliput_sys::api::ffi::BulbState::kBlinking => Some(rules::BulbState::Blinking),
_ => None,
}
}
pub fn discrete_value_rule_states(&self) -> Vec<rules::DiscreteValueRuleState> {
maliput_sys::api::ffi::Intersection_DiscreteValueRuleStates(self.intersection)
.iter()
.map(|dvrs| rules::DiscreteValueRuleState {
rule_id: dvrs.rule_id.clone(),
state: rules::discrete_value_from_discrete_value_cxx(&dvrs.state),
})
.collect::<Vec<rules::DiscreteValueRuleState>>()
}
pub fn includes_traffic_light(&self, traffic_light_id: &str) -> bool {
maliput_sys::api::ffi::Intersection_IncludesTrafficLight(self.intersection, &traffic_light_id.to_string())
}
pub fn includes_discrete_value_rule(&self, rule_id: &str) -> bool {
maliput_sys::api::ffi::Intersection_IncludesDiscreteValueRule(self.intersection, &rule_id.to_string())
}
pub fn includes_inertial_position(
&self,
inertial_position: &InertialPosition,
road_geometry: &RoadGeometry,
) -> bool {
maliput_sys::api::ffi::Intersection_IncludesInertialPosition(
self.intersection,
&maliput_sys::api::ffi::InertialPosition_new(
inertial_position.x(),
inertial_position.y(),
inertial_position.z(),
),
road_geometry.rg,
)
}
}
pub struct IntersectionBook<'a> {
intersection_book: &'a maliput_sys::api::ffi::IntersectionBook,
}
impl<'a> IntersectionBook<'a> {
pub fn get_intersections(&self) -> Vec<Intersection<'_>> {
let intersections_cpp = maliput_sys::api::ffi::IntersectionBook_GetIntersections(self.intersection_book);
unsafe {
intersections_cpp
.into_iter()
.map(|intersection| Intersection {
intersection: intersection
.intersection
.as_ref()
.expect("Underlying Intersection is null"),
})
.collect::<Vec<Intersection>>()
}
}
pub fn get_intersection(&self, id: &str) -> Option<Intersection<'_>> {
let intersection_option = unsafe {
maliput_sys::api::ffi::IntersectionBook_GetIntersection(self.intersection_book, &String::from(id))
.intersection
.as_ref()
};
intersection_option.map(|intersection| Intersection { intersection })
}
pub fn find_intersection_with_traffic_light(&self, traffic_light_id: &str) -> Option<Intersection<'_>> {
let intersection = maliput_sys::api::ffi::IntersectionBook_FindIntersectionTrafficLight(
self.intersection_book,
&String::from(traffic_light_id),
);
if intersection.intersection.is_null() {
return None;
}
unsafe {
Some(Intersection {
intersection: intersection
.intersection
.as_ref()
.expect("Underlying Intersection is null"),
})
}
}
pub fn find_intersection_with_discrete_value_rule(&self, rule_id: &str) -> Option<Intersection<'_>> {
let intersection = maliput_sys::api::ffi::IntersectionBook_FindIntersectionDiscreteValueRule(
self.intersection_book,
&String::from(rule_id),
);
if intersection.intersection.is_null() {
return None;
}
unsafe {
Some(Intersection {
intersection: intersection
.intersection
.as_ref()
.expect("Underlying Intersection is null"),
})
}
}
pub fn find_intersection_with_inertial_position(
&self,
inertial_position: &InertialPosition,
) -> Option<Intersection<'_>> {
let intersection = maliput_sys::api::ffi::IntersectionBook_FindIntersectionInertialPosition(
self.intersection_book,
&inertial_position.ip,
);
if intersection.intersection.is_null() {
return None;
}
unsafe {
Some(Intersection {
intersection: intersection
.intersection
.as_ref()
.expect("Underlying Intersection is null"),
})
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct LaneMarkingLine {
pub length: f64,
pub space: f64,
pub width: f64,
pub r_offset: f64,
pub color: LaneMarkingColor,
}
impl LaneMarkingLine {
pub fn new(length: f64, space: f64, width: f64, r_offset: f64, color: LaneMarkingColor) -> LaneMarkingLine {
LaneMarkingLine {
length,
space,
width,
r_offset,
color,
}
}
}
#[derive(strum_macros::Display, Debug, Copy, Clone, PartialEq, Eq)]
pub enum LaneMarkingType {
Unknown,
None,
Solid,
Broken,
SolidSolid,
SolidBroken,
BrokenSolid,
BrokenBroken,
BottsDots,
Grass,
Curb,
Edge,
}
#[derive(strum_macros::Display, Debug, Copy, Clone, PartialEq, Eq)]
pub enum LaneMarkingWeight {
Unknown,
Standard,
Bold,
}
#[derive(strum_macros::Display, Debug, Copy, Clone, PartialEq, Eq)]
pub enum LaneMarkingColor {
Unknown,
White,
Yellow,
Orange,
Red,
Blue,
Green,
Violet,
}
#[derive(strum_macros::Display, Debug, Copy, Clone, PartialEq, Eq)]
pub enum LaneChangePermission {
Unknown,
Allowed,
ToLeft,
ToRight,
Prohibited,
}
pub struct LaneMarking {
lane_marking: cxx::UniquePtr<maliput_sys::api::ffi::LaneMarking>,
}
impl LaneMarking {
pub fn width(&self) -> f64 {
maliput_sys::api::ffi::LaneMarking_width(&self.lane_marking)
}
pub fn height(&self) -> f64 {
maliput_sys::api::ffi::LaneMarking_height(&self.lane_marking)
}
pub fn material(&self) -> String {
maliput_sys::api::ffi::LaneMarking_material(&self.lane_marking)
}
pub fn get_type(&self) -> LaneMarkingType {
let marking_type = maliput_sys::api::ffi::LaneMarking_type(&self.lane_marking);
match marking_type {
maliput_sys::api::ffi::LaneMarkingType::kUnknown => LaneMarkingType::Unknown,
maliput_sys::api::ffi::LaneMarkingType::kNone => LaneMarkingType::None,
maliput_sys::api::ffi::LaneMarkingType::kSolid => LaneMarkingType::Solid,
maliput_sys::api::ffi::LaneMarkingType::kBroken => LaneMarkingType::Broken,
maliput_sys::api::ffi::LaneMarkingType::kSolidSolid => LaneMarkingType::SolidSolid,
maliput_sys::api::ffi::LaneMarkingType::kSolidBroken => LaneMarkingType::SolidBroken,
maliput_sys::api::ffi::LaneMarkingType::kBrokenSolid => LaneMarkingType::BrokenSolid,
maliput_sys::api::ffi::LaneMarkingType::kBrokenBroken => LaneMarkingType::BrokenBroken,
maliput_sys::api::ffi::LaneMarkingType::kBottsDots => LaneMarkingType::BottsDots,
maliput_sys::api::ffi::LaneMarkingType::kGrass => LaneMarkingType::Grass,
maliput_sys::api::ffi::LaneMarkingType::kCurb => LaneMarkingType::Curb,
maliput_sys::api::ffi::LaneMarkingType::kEdge => LaneMarkingType::Edge,
_ => LaneMarkingType::Unknown,
}
}
pub fn weight(&self) -> LaneMarkingWeight {
let marking_weight = maliput_sys::api::ffi::LaneMarking_weight(&self.lane_marking);
match marking_weight {
maliput_sys::api::ffi::LaneMarkingWeight::kUnknown => LaneMarkingWeight::Unknown,
maliput_sys::api::ffi::LaneMarkingWeight::kStandard => LaneMarkingWeight::Standard,
maliput_sys::api::ffi::LaneMarkingWeight::kBold => LaneMarkingWeight::Bold,
_ => LaneMarkingWeight::Unknown,
}
}
pub fn color(&self) -> LaneMarkingColor {
self.get_marking_color(maliput_sys::api::ffi::LaneMarking_color(&self.lane_marking))
}
pub fn lane_change(&self) -> LaneChangePermission {
let lane_change = maliput_sys::api::ffi::LaneMarking_lane_change(&self.lane_marking);
match lane_change {
maliput_sys::api::ffi::LaneChangePermission::kUnknown => LaneChangePermission::Unknown,
maliput_sys::api::ffi::LaneChangePermission::kAllowed => LaneChangePermission::Allowed,
maliput_sys::api::ffi::LaneChangePermission::kToLeft => LaneChangePermission::ToLeft,
maliput_sys::api::ffi::LaneChangePermission::kToRight => LaneChangePermission::ToRight,
maliput_sys::api::ffi::LaneChangePermission::kProhibited => LaneChangePermission::Prohibited,
_ => LaneChangePermission::Unknown,
}
}
pub fn lines(&self) -> Vec<LaneMarkingLine> {
let lines = maliput_sys::api::ffi::LaneMarking_lines(&self.lane_marking);
lines
.into_iter()
.map(|line| LaneMarkingLine {
length: maliput_sys::api::ffi::LaneMarkingLine_length(line),
space: maliput_sys::api::ffi::LaneMarkingLine_space(line),
width: maliput_sys::api::ffi::LaneMarkingLine_width(line),
r_offset: maliput_sys::api::ffi::LaneMarkingLine_r_offset(line),
color: self.get_marking_color(maliput_sys::api::ffi::LaneMarkingLine_color(line)),
})
.collect::<Vec<LaneMarkingLine>>()
}
fn get_marking_color(&self, color: maliput_sys::api::ffi::LaneMarkingColor) -> LaneMarkingColor {
match color {
maliput_sys::api::ffi::LaneMarkingColor::kUnknown => LaneMarkingColor::Unknown,
maliput_sys::api::ffi::LaneMarkingColor::kWhite => LaneMarkingColor::White,
maliput_sys::api::ffi::LaneMarkingColor::kYellow => LaneMarkingColor::Yellow,
maliput_sys::api::ffi::LaneMarkingColor::kOrange => LaneMarkingColor::Orange,
maliput_sys::api::ffi::LaneMarkingColor::kRed => LaneMarkingColor::Red,
maliput_sys::api::ffi::LaneMarkingColor::kBlue => LaneMarkingColor::Blue,
maliput_sys::api::ffi::LaneMarkingColor::kGreen => LaneMarkingColor::Green,
maliput_sys::api::ffi::LaneMarkingColor::kViolet => LaneMarkingColor::Violet,
_ => LaneMarkingColor::Unknown,
}
}
}
pub struct LaneMarkingQuery {
pub lane_marking: LaneMarking,
pub s_start: f64,
pub s_end: f64,
}
pub struct LaneBoundary<'a> {
lane_boundary: &'a maliput_sys::api::ffi::LaneBoundary,
}
impl<'a> LaneBoundary<'a> {
pub fn id(&self) -> String {
maliput_sys::api::ffi::LaneBoundary_id(self.lane_boundary)
}
pub fn segment(&self) -> Option<Segment<'a>> {
let segment = self.lane_boundary.segment();
if segment.is_null() {
return None;
}
Some(unsafe {
Segment {
segment: segment.as_ref().expect(""),
}
})
}
pub fn index(&self) -> i32 {
self.lane_boundary.index()
}
pub fn lane_to_left(&self) -> Option<Lane<'a>> {
let lane = self.lane_boundary.lane_to_left();
if lane.is_null() {
return None;
}
Some(unsafe {
Lane {
lane: lane.as_ref().expect("Lane pointer from lane_to_left is null"),
}
})
}
pub fn lane_to_right(&self) -> Option<Lane<'a>> {
let lane = self.lane_boundary.lane_to_right();
if lane.is_null() {
return None;
}
Some(unsafe {
Lane {
lane: lane.as_ref().expect("Lane pointer from lane_to_right is null"),
}
})
}
pub fn get_marking(&self, s: f64) -> Option<LaneMarkingQuery> {
let lane_marking_query = maliput_sys::api::ffi::LaneBoundary_GetMarking(self.lane_boundary, s);
if lane_marking_query.is_null() {
return None;
}
Some(self.create_lane_marking_query(&lane_marking_query))
}
pub fn get_markings(&self) -> Vec<LaneMarkingQuery> {
let lane_marking_queries = maliput_sys::api::ffi::LaneBoundary_GetMarkings(self.lane_boundary);
lane_marking_queries
.into_iter()
.map(|lane_marking_query| self.create_lane_marking_query(lane_marking_query))
.collect::<Vec<LaneMarkingQuery>>()
}
pub fn get_markings_by_range(&self, s_start: f64, s_end: f64) -> Vec<LaneMarkingQuery> {
let lane_marking_queries =
maliput_sys::api::ffi::LaneBoundary_GetMarkingsByRange(self.lane_boundary, s_start, s_end);
lane_marking_queries
.into_iter()
.map(|lane_marking_query| self.create_lane_marking_query(lane_marking_query))
.collect::<Vec<LaneMarkingQuery>>()
}
fn create_lane_marking_query(
&self,
lane_marking_query: &maliput_sys::api::ffi::LaneMarkingResult,
) -> LaneMarkingQuery {
LaneMarkingQuery {
lane_marking: LaneMarking {
lane_marking: maliput_sys::api::ffi::LaneMarkingResult_marking(lane_marking_query),
},
s_start: maliput_sys::api::ffi::LaneMarkingResult_s_start(lane_marking_query),
s_end: maliput_sys::api::ffi::LaneMarkingResult_s_end(lane_marking_query),
}
}
}
mod tests {
mod road_geometry {
#[test]
fn to_road_position_surface_test() {
let package_location = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let xodr_path = format!("{}/data/xodr/TShapeRoad.xodr", package_location);
let road_network_properties = std::collections::HashMap::from([
("road_geometry_id", "my_rg_from_rust"),
("opendrive_file", xodr_path.as_str()),
]);
let road_network = crate::api::RoadNetwork::new(
crate::api::RoadNetworkBackend::MaliputMalidrive,
&road_network_properties,
)
.unwrap();
let road_geometry = road_network.road_geometry();
let inertial_pos = crate::api::InertialPosition::new(1.0, 0.0, 2.0);
let road_pos = road_geometry.to_road_position_surface(&inertial_pos);
assert!(road_pos.is_ok());
let road_pos = road_pos.unwrap();
let tolerance = 1e-3;
assert!((road_pos.pos().s() - 1.0).abs() < tolerance);
assert!((road_pos.pos().r() - -1.75).abs() < tolerance);
assert!((road_pos.pos().h() - 0.0).abs() < tolerance);
let inertial_pos = crate::api::InertialPosition::new(1.0, 0.0, 10.0);
let road_pos = road_geometry.to_road_position_surface(&inertial_pos);
assert!(road_pos.is_err());
}
}
mod lane_position {
#[test]
fn lane_position_new() {
let lane_pos = crate::api::LanePosition::new(1.0, 2.0, 3.0);
assert_eq!(lane_pos.s(), 1.0);
assert_eq!(lane_pos.r(), 2.0);
assert_eq!(lane_pos.h(), 3.0);
}
#[test]
fn equality() {
let v = crate::api::LanePosition::new(1.0, 2.0, 3.0);
let w = crate::api::LanePosition::new(1.0, 2.0, 3.0);
assert_eq!(v, w);
let z = crate::api::LanePosition::new(4.0, 5.0, 6.0);
assert_ne!(v, z);
}
#[test]
fn set_s() {
let mut lane_pos = crate::api::LanePosition::new(1.0, 2.0, 3.0);
lane_pos.set_s(4.0);
assert_eq!(lane_pos.s(), 4.0);
}
#[test]
fn set_r() {
let mut lane_pos = crate::api::LanePosition::new(1.0, 2.0, 3.0);
lane_pos.set_r(4.0);
assert_eq!(lane_pos.r(), 4.0);
}
#[test]
fn set_h() {
let mut lane_pos = crate::api::LanePosition::new(1.0, 2.0, 3.0);
lane_pos.set_h(4.0);
assert_eq!(lane_pos.h(), 4.0);
}
#[test]
fn set_srh() {
use crate::math::Vector3;
let mut lane_pos = crate::api::LanePosition::new(1.0, 2.0, 3.0);
let vector = Vector3::new(4.0, 5.0, 6.0);
lane_pos.set_srh(&vector);
assert_eq!(lane_pos.s(), 4.0);
assert_eq!(lane_pos.r(), 5.0);
assert_eq!(lane_pos.h(), 6.0);
}
}
mod inertial_position {
#[test]
fn inertial_position_new() {
let inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
assert_eq!(inertial_pos.x(), 1.0);
assert_eq!(inertial_pos.y(), 2.0);
assert_eq!(inertial_pos.z(), 3.0);
}
#[test]
fn equality() {
let v = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
let w = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
assert_eq!(v, w);
let z = crate::api::InertialPosition::new(4.0, 5.0, 6.0);
assert_ne!(v, z);
}
#[test]
fn set_x() {
let mut inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
inertial_pos.set_x(4.0);
assert_eq!(inertial_pos.x(), 4.0);
}
#[test]
fn set_y() {
let mut inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
inertial_pos.set_y(4.0);
assert_eq!(inertial_pos.y(), 4.0);
}
#[test]
fn set_z() {
let mut inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
inertial_pos.set_z(4.0);
assert_eq!(inertial_pos.z(), 4.0);
}
#[test]
fn set_xyz() {
use crate::math::Vector3;
let mut inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
let vector = Vector3::new(4.0, 5.0, 6.0);
inertial_pos.set_xyz(&vector);
assert_eq!(inertial_pos.x(), 4.0);
assert_eq!(inertial_pos.y(), 5.0);
assert_eq!(inertial_pos.z(), 6.0);
}
#[test]
fn xyz() {
let inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
assert_eq!(inertial_pos.xyz(), crate::math::Vector3::new(1.0, 2.0, 3.0));
}
#[test]
fn length() {
let inertial_pos = crate::api::InertialPosition::new(3.0, 0.0, 4.0);
assert_eq!(inertial_pos.length(), 5.0);
}
#[test]
fn distance() {
let inertial_pos1 = crate::api::InertialPosition::new(1.0, 1.0, 1.0);
let inertial_pos2 = crate::api::InertialPosition::new(5.0, 1.0, 1.0);
assert_eq!(inertial_pos1.distance(&inertial_pos2), 4.0);
}
#[test]
fn str() {
let inertial_pos = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
assert_eq!(inertial_pos.to_string(), "(x = 1, y = 2, z = 3)");
}
#[test]
fn add_operation() {
let inertial_pos1 = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
let inertial_pos2 = crate::api::InertialPosition::new(4.0, 5.0, 6.0);
let inertial_pos3 = inertial_pos1 + inertial_pos2;
assert_eq!(inertial_pos3.x(), 5.0);
assert_eq!(inertial_pos3.y(), 7.0);
assert_eq!(inertial_pos3.z(), 9.0);
}
#[test]
fn sub_operation() {
let inertial_pos1 = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
let inertial_pos2 = crate::api::InertialPosition::new(4.0, 5.0, 6.0);
let inertial_pos3 = inertial_pos1 - inertial_pos2;
assert_eq!(inertial_pos3.x(), -3.0);
assert_eq!(inertial_pos3.y(), -3.0);
assert_eq!(inertial_pos3.z(), -3.0);
}
#[test]
fn mul_scalar_operation() {
let inertial_pos1 = crate::api::InertialPosition::new(1.0, 2.0, 3.0);
let inertial_pos2 = inertial_pos1 * 2.0;
assert_eq!(inertial_pos2.x(), 2.0);
assert_eq!(inertial_pos2.y(), 4.0);
assert_eq!(inertial_pos2.z(), 6.0);
}
}
mod rotation {
#[test]
fn rotation_new() {
let rotation = crate::api::Rotation::new();
assert_eq!(rotation.roll(), 0.0);
assert_eq!(rotation.pitch(), 0.0);
assert_eq!(rotation.yaw(), 0.0);
}
#[test]
fn from_quat() {
let quat = crate::math::Quaternion::new(1.0, 0.0, 0.0, 0.0);
let rotation = crate::api::Rotation::from_quat(&quat);
assert_eq!(rotation.roll(), 0.0);
assert_eq!(rotation.pitch(), 0.0);
assert_eq!(rotation.yaw(), 0.0);
}
#[test]
fn from_rpy() {
let rpy = crate::math::RollPitchYaw::new(0.0, 0.0, 0.0);
let rotation = crate::api::Rotation::from_rpy(&rpy);
assert_eq!(rotation.roll(), 0.0);
assert_eq!(rotation.pitch(), 0.0);
assert_eq!(rotation.yaw(), 0.0);
}
#[test]
fn set_quat() {
let mut rotation = crate::api::Rotation::new();
let quat = crate::math::Quaternion::new(1.0, 0.0, 0.0, 0.0);
rotation.set_quat(&quat);
assert_eq!(rotation.roll(), 0.0);
assert_eq!(rotation.pitch(), 0.0);
assert_eq!(rotation.yaw(), 0.0);
}
#[test]
fn matrix() {
let rotation = crate::api::Rotation::new();
let matrix = rotation.matrix();
assert_eq!(matrix.row(0), crate::math::Vector3::new(1.0, 0.0, 0.0));
assert_eq!(matrix.row(1), crate::math::Vector3::new(0.0, 1.0, 0.0));
assert_eq!(matrix.row(2), crate::math::Vector3::new(0.0, 0.0, 1.0));
}
}
mod s_range {
#[test]
fn s_range_new() {
let s_range = crate::api::SRange::new(1.0, 2.0);
assert_eq!(s_range.s0(), 1.0);
assert_eq!(s_range.s1(), 2.0);
}
#[test]
fn s_range_api() {
let s_range_1 = crate::api::SRange::new(1.0, 3.0);
let s_range_2 = crate::api::SRange::new(2.0, 4.0);
assert_eq!(s_range_1.size(), 2.0);
assert!(s_range_1.with_s());
assert!(s_range_1.intersects(&s_range_2, 0.0));
assert!(!s_range_1.contains(&s_range_2, 0.0));
}
#[test]
fn s_range_setters() {
let mut s_range = crate::api::SRange::new(0.0, 4.0);
s_range.set_s0(1.0);
s_range.set_s1(3.0);
assert_eq!(s_range.s0(), 1.0);
assert_eq!(s_range.s1(), 3.0);
}
#[test]
fn s_range_get_intersection_with_intersection() {
let s_range_1 = crate::api::SRange::new(1.0, 3.0);
let s_range_2 = crate::api::SRange::new(2.0, 4.0);
let intersection = s_range_1.get_intersection(&s_range_2, 0.0);
assert!(intersection.is_some());
let intersection = intersection.unwrap();
assert_eq!(intersection.s0(), 2.0);
assert_eq!(intersection.s1(), 3.0);
}
#[test]
fn s_range_get_intersection_with_no_intersection() {
let s_range_1 = crate::api::SRange::new(1.0, 2.0);
let s_range_2 = crate::api::SRange::new(3.0, 4.0);
let intersection = s_range_1.get_intersection(&s_range_2, 0.0);
assert!(intersection.is_none());
}
}
mod lane_s_range {
#[test]
fn lane_s_range_new() {
let lane_s_range =
crate::api::LaneSRange::new(&String::from("lane_test"), &crate::api::SRange::new(1.0, 2.0));
assert_eq!(lane_s_range.lane_id(), "lane_test");
assert_eq!(lane_s_range.s_range().s0(), 1.0);
assert_eq!(lane_s_range.s_range().s1(), 2.0);
assert_eq!(lane_s_range.length(), 1.0);
}
#[test]
fn lane_s_range_api() {
let lane_s_range_1 =
crate::api::LaneSRange::new(&String::from("lane_test"), &crate::api::SRange::new(1.0, 2.0));
let lane_s_range_2 =
crate::api::LaneSRange::new(&String::from("lane_test"), &crate::api::SRange::new(2.0, 3.0));
assert!(lane_s_range_1.intersects(&lane_s_range_2, 0.0));
assert!(!lane_s_range_1.contains(&lane_s_range_2, 0.0));
}
#[test]
fn lane_s_range_get_intersection_with_intersection() {
let lane_s_range_1 =
crate::api::LaneSRange::new(&String::from("lane_test"), &crate::api::SRange::new(1.0, 3.0));
let lane_s_range_2 =
crate::api::LaneSRange::new(&String::from("lane_test"), &crate::api::SRange::new(2.0, 4.0));
let intersection = lane_s_range_1.get_intersection(&lane_s_range_2, 0.0);
assert!(intersection.is_some());
let intersection = intersection.unwrap();
assert_eq!(intersection.lane_id(), "lane_test");
assert_eq!(intersection.s_range().s0(), 2.0);
assert_eq!(intersection.s_range().s1(), 3.0);
}
#[test]
fn lane_s_range_get_intersection_with_no_intersection() {
let lane_s_range_1 =
crate::api::LaneSRange::new(&String::from("lane test_1"), &crate::api::SRange::new(1.0, 3.0));
let lane_s_range_2 =
crate::api::LaneSRange::new(&String::from("lane_test_2"), &crate::api::SRange::new(2.0, 4.0));
let intersection = lane_s_range_1.get_intersection(&lane_s_range_2, 0.0);
assert!(intersection.is_none());
}
}
mod lane_s_route {
fn _get_lane_s_route(s0_0: f64, s1_0: f64, s0_1: f64, s1_1: f64) -> crate::api::LaneSRoute {
let ranges = vec![
crate::api::LaneSRange::new(&String::from("lane_test_1"), &crate::api::SRange::new(s0_0, s1_0)),
crate::api::LaneSRange::new(&String::from("lane_test_2"), &crate::api::SRange::new(s0_1, s1_1)),
];
crate::api::LaneSRoute::new(ranges)
}
#[test]
fn lane_s_route_new() {
let lane_s_route = _get_lane_s_route(0., 10., 0., 15.);
assert!(!lane_s_route.lane_s_route.is_null());
let ranges = lane_s_route.ranges();
assert_eq!(ranges.len(), 2);
assert_eq!(ranges[0].lane_id(), "lane_test_1");
assert_eq!(ranges[1].lane_id(), "lane_test_2");
}
#[test]
fn lane_s_route_length() {
let lane_s_route = _get_lane_s_route(0., 10., 0., 15.);
assert_eq!(lane_s_route.length(), 25.0);
}
#[test]
fn lane_s_route_intersects() {
let lane_s_route = _get_lane_s_route(0., 10., 0., 10.);
let lane_s_route_that_intersects = _get_lane_s_route(5., 9., 5., 9.);
let lane_s_route_that_not_intersects = _get_lane_s_route(11., 20., 11., 20.);
assert!(lane_s_route.intersects(&lane_s_route_that_intersects, 0.0));
assert!(!lane_s_route.intersects(&lane_s_route_that_not_intersects, 0.0));
}
}
}