Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds zone method to rules api. #122

Merged
merged 3 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions maliput-sys/src/api/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,15 @@ std::unique_ptr<LaneSRange> LaneSRange_GetIntersection(const LaneSRange& lane_s_
return nullptr;
}

std::unique_ptr<LaneSRoute> LaneSRoute_new(const std::vector<ConstLaneSRangeRef>& lane_s_ranges) {
std::vector<LaneSRange> lane_s_ranges_cpp;
lane_s_ranges_cpp.reserve(lane_s_ranges.size());
for (const auto& lane_s_range : lane_s_ranges) {
lane_s_ranges_cpp.push_back(LaneSRange{lane_s_range.lane_s_range.lane_id(), lane_s_range.lane_s_range.s_range()});
}
return std::make_unique<LaneSRoute>(lane_s_ranges_cpp);
}

std::unique_ptr<LaneEnd> LaneEnd_new(const Lane* lane, bool start) {
return std::make_unique<LaneEnd>(lane, start ? LaneEnd::kStart : LaneEnd::kFinish);
}
Expand Down
12 changes: 12 additions & 0 deletions maliput-sys/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ pub mod ffi {
struct MutIntersectionPtr {
pub intersection: *mut Intersection,
}
/// Shared struct for `LaneSRange` references.
/// This is needed because `&f` can't be used directly in the CxxVector collection.
struct ConstLaneSRangeRef<'a> {
pub lane_s_range: &'a LaneSRange,
}

unsafe extern "C++" {
include!("api/api.h");
Expand Down Expand Up @@ -233,6 +238,13 @@ pub mod ffi {
tolerance: f64,
) -> UniquePtr<LaneSRange>;

// LaneSRoute bindings definitions
type LaneSRoute;
fn LaneSRoute_new(ranges: &CxxVector<ConstLaneSRangeRef>) -> UniquePtr<LaneSRoute>;
fn length(self: &LaneSRoute) -> f64;
fn Intersects(self: &LaneSRoute, other: &LaneSRoute, tolerance: f64) -> bool;
fn ranges(self: &LaneSRoute) -> &CxxVector<LaneSRange>;

// LaneEnd bindings definitions
type LaneEnd;
// maliput::api Rust will have its own LaneEnd enum.
Expand Down
4 changes: 4 additions & 0 deletions maliput-sys/src/api/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ pub mod ffi {
type InertialPosition = crate::api::ffi::InertialPosition;
#[namespace = "maliput::api"]
type Rotation = crate::api::ffi::Rotation;
#[namespace = "maliput::api"]
type LaneSRoute = crate::api::ffi::LaneSRoute;
#[namespace = "maliput::math"]
type Vector3 = crate::math::ffi::Vector3;

Expand Down Expand Up @@ -181,6 +183,7 @@ pub mod ffi {
fn states(self: &DiscreteValueRule) -> &CxxVector<DiscreteValueRuleDiscreteValue>;
fn DiscreteValueRule_id(rule: &DiscreteValueRule) -> String;
fn DiscreteValueRule_type_id(rule: &DiscreteValueRule) -> String;
fn DiscreteValueRule_zone(rule: &DiscreteValueRule) -> UniquePtr<LaneSRoute>;

// RangeValueRule::Range bindings definitions.
type RangeValueRuleRange;
Expand All @@ -195,6 +198,7 @@ pub mod ffi {
type RangeValueRule;
fn RangeValueRule_id(rule: &RangeValueRule) -> String;
fn RangeValueRule_type_id(rule: &RangeValueRule) -> String;
fn RangeValueRule_zone(rule: &RangeValueRule) -> UniquePtr<LaneSRoute>;
fn states(self: &RangeValueRule) -> &CxxVector<RangeValueRuleRange>;
}
}
8 changes: 8 additions & 0 deletions maliput-sys/src/api/rules/rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,10 @@ rust::String DiscreteValueRule_type_id(const DiscreteValueRule& rule) {
return rule.type_id().string();
}

std::unique_ptr<LaneSRoute> DiscreteValueRule_zone(const DiscreteValueRule& rule) {
return std::make_unique<LaneSRoute>(rule.zone());
}

rust::String RangeValueRuleRange_description(const RangeValueRuleRange& range) {
return rust::String(range.description);
}
Expand Down Expand Up @@ -273,6 +277,10 @@ rust::String RangeValueRule_type_id(const RangeValueRule& rule) {
return rule.type_id().string();
}

std::unique_ptr<LaneSRoute> RangeValueRule_zone(const RangeValueRule& rule) {
return std::make_unique<LaneSRoute>(rule.zone());
}

std::unique_ptr<RangeValueRule> RoadRulebook_GetRangeValueRule(const RoadRulebook& road_rulebook, const rust::String& id) {
return std::make_unique<RangeValueRule>(road_rulebook.GetRangeValueRule(Rule::Id{std::string(id)}));
}
Expand Down
36 changes: 36 additions & 0 deletions maliput-sys/tests/api_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,4 +353,40 @@ mod api_test {
assert_eq!(s_range.s1(), 2.0);
}
}

mod lane_s_route_test {
use maliput_sys::api::ffi::ConstLaneSRangeRef;
use maliput_sys::api::ffi::LaneSRange_lane_id;
use maliput_sys::api::ffi::LaneSRange_new;
use maliput_sys::api::ffi::LaneSRoute_new;
use maliput_sys::api::ffi::SRange_new;
#[test]
fn lane_s_route_api() {
let s_range = SRange_new(1.0, 2.0);
let lane_id = String::from("0_0_1");
let lane_s_range_1 = LaneSRange_new(&lane_id, &s_range);
let lane_id = String::from("1_0_1");
let lane_s_range_2 = LaneSRange_new(&lane_id, &s_range);

let mut v = cxx::CxxVector::new();
v.as_mut().unwrap().push(ConstLaneSRangeRef {
lane_s_range: &lane_s_range_1,
});
v.as_mut().unwrap().push(ConstLaneSRangeRef {
lane_s_range: &lane_s_range_2,
});
let lane_s_route = LaneSRoute_new(&v);
assert!(!lane_s_route.is_null());
// Ranges
let ranges = lane_s_route.ranges();
assert_eq!(ranges.len(), 2);
assert_eq!(LaneSRange_lane_id(ranges.get(0).expect("")), "0_0_1");
assert_eq!(LaneSRange_lane_id(ranges.get(1).expect("")), "1_0_1");
// Length
assert_eq!(lane_s_route.length(), 2.0);
// Intersects
let lane_s_route_b = LaneSRoute_new(&v);
assert!(lane_s_route.Intersects(&lane_s_route_b, 1e-3));
}
}
}
102 changes: 102 additions & 0 deletions maliput/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,69 @@ impl LaneSRange {
}
}

/// A route, possibly spanning multiple (end-to-end) lanes.
///
/// The sequence of [LaneSRange]s should be contiguous by either presenting
/// laterally adjacent [LaneSRange]s, or consecutive [LaneSRange]s. (In other words,
/// taken as a Lane-space path with r=0 and h=0, it should present a
/// G1-continuous curve.)
pub struct LaneSRoute {
lane_s_route: cxx::UniquePtr<maliput_sys::api::ffi::LaneSRoute>,
}

impl LaneSRoute {
/// Create a new `LaneSRoute` with the given `ranges`.
///
/// ## Arguments
/// * `ranges` - A vector of [LaneSRange] to create the [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),
}
}

/// Returns the sequence of [LaneSRange]s.
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
}

/// Computes the accumulated length of all [LaneSRange]s.
pub fn length(&self) -> f64 {
self.lane_s_route.length()
}

/// Determines whether this LaneSRoute intersects with `other`.
///
/// ## Arguments
/// * `other` - The other LaneSRoute to check for intersection.
/// * `tolerance` - The tolerance to use for intersection checks.
///
/// ## Returns
/// * `true` if the two LaneSRoute intersect, `false` otherwise.
pub fn intersects(&self, other: &LaneSRoute, tolerance: f64) -> bool {
self.lane_s_route.Intersects(&other.lane_s_route, tolerance)
}
}

/// A specific endpoint of a specific Lane.
/// This is analogous to the C++ maliput::api::LaneEnd implementation.
pub enum LaneEnd<'a> {
Expand Down Expand Up @@ -1681,4 +1744,43 @@ mod tests {
assert!(intersection.is_none());
}
}

mod lane_s_route {
// Helper function to create a LaneSRoute
// with two LaneSRange.
// ## Arguments
// * `s0_0` - The s0 of the first LaneSRange.
// * `s1_0` - The s1 of the first LaneSRange.
// * `s0_1` - The s0 of the second LaneSRange.
// * `s1_1` - The s1 of the second LaneSRange.
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));
}
}
}
10 changes: 6 additions & 4 deletions maliput/src/api/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,8 +548,9 @@ impl DiscreteValueRule {
maliput_sys::api::rules::ffi::DiscreteValueRule_type_id(&self.discrete_value_rule)
}
/// Returns a [LaneSRoute] that represents the zone that the rule applies to.
pub fn zone(&self) {
unimplemented!("Not yet implemented")
pub fn zone(&self) -> crate::api::LaneSRoute {
let lane_s_route = maliput_sys::api::rules::ffi::DiscreteValueRule_zone(&self.discrete_value_rule);
crate::api::LaneSRoute { lane_s_route }
}
/// Returns the states of the rule.
pub fn states(&self) -> Vec<DiscreteValue> {
Expand Down Expand Up @@ -602,8 +603,9 @@ impl RangeValueRule {
maliput_sys::api::rules::ffi::RangeValueRule_type_id(&self.range_value_rule)
}
/// Returns a [LaneSRoute] that represents the zone that the rule applies to.
pub fn zone(&self) {
unimplemented!("Not yet implemented")
pub fn zone(&self) -> crate::api::LaneSRoute {
let lane_s_route = maliput_sys::api::rules::ffi::RangeValueRule_zone(&self.range_value_rule);
crate::api::LaneSRoute { lane_s_route }
}
/// Returns the states of the rule.
pub fn states(&self) -> Vec<Range> {
Expand Down
4 changes: 4 additions & 0 deletions maliput/tests/discrete_value_rule_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mod common;

#[test]
fn discrete_value_rule_test_api() {
static TOLERANCE: f64 = 1e-9;
use maliput::api::rules::RuleState;

let road_network = common::create_loop_road_pedestrian_crosswalk_road_network_with_books();
Expand All @@ -45,6 +46,9 @@ fn discrete_value_rule_test_api() {
let rule = book.get_discrete_value_rule(&expected_rule_id);
assert_eq!(rule.id(), expected_rule_id);
assert_eq!(rule.type_id(), expected_type_id);
let zone = rule.zone();
let expected_zone_length = 15.;
assert!((zone.length() - expected_zone_length).abs() < TOLERANCE);

let states = rule.states();
assert_eq!(states.len(), 2); // Go and Stop
Expand Down
4 changes: 4 additions & 0 deletions maliput/tests/range_value_rule_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mod common;

#[test]
fn range_value_rule_test_api() {
static TOLERANCE: f64 = 1e-9;
use maliput::api::rules::RuleState;

let road_network = common::create_loop_road_pedestrian_crosswalk_road_network_with_books();
Expand All @@ -45,6 +46,9 @@ fn range_value_rule_test_api() {
let rule = book.get_range_value_rule(&expected_rule_id);
assert_eq!(rule.id(), expected_rule_id);
assert_eq!(rule.type_id(), expected_type_id);
let zone = rule.zone();
let expected_zone_length = 15.;
assert!((zone.length() - expected_zone_length).abs() < TOLERANCE);

let states = rule.states();
assert_eq!(states.len(), 1); // Only one speed limit state
Expand Down