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 bindings/rust API for BulbGroup abstraction. #104

Merged
merged 1 commit into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 25 additions & 2 deletions maliput-sys/src/api/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,20 @@
#[cxx::bridge(namespace = "maliput::api::rules")]
pub mod ffi {
/// Shared struct for `TrafficLight` pointers.
/// This is needed because `*const f` can't be used directly in the CxxVector collection.
/// This is needed because `*const` can't be used directly in the CxxVector collection.
struct ConstTrafficLightPtr {
pub traffic_light: *const TrafficLight,
}
/// Shared struct for `BulbGroup` pointers.
/// This is needed because `*const` can't be used directly in the CxxVector collection.
struct ConstBulbGroupPtr {
pub bulb_group: *const BulbGroup,
}
/// Shared struct for `Bulb` pointers.
/// This is needed because `*const` can't be used directly in the CxxVector collection.
struct ConstBulbPtr {
pub bulb: *const Bulb,
}
/// Shared struct for `BulbState` references.
/// This is needed because `&f` can't be used directly in the CxxVector collection.
struct ConstBulbStateRef<'a> {
Expand Down Expand Up @@ -87,10 +97,13 @@ pub mod ffi {
fn TrafficLight_id(traffic_light: &TrafficLight) -> String;
fn TrafficLight_position_road_network(traffic_light: &TrafficLight) -> UniquePtr<InertialPosition>;
fn TrafficLight_orientation_road_network(traffic_light: &TrafficLight) -> UniquePtr<Rotation>;
fn TrafficLight_bulb_groups(traffic_light: &TrafficLight) -> UniquePtr<CxxVector<ConstBulbGroupPtr>>;
fn TrafficLight_GetBulbGroup(traffic_light: &TrafficLight, id: &String) -> *const BulbGroup;

type BulbColor;
type BulbState;
type BulbType;
// Bulb bindings definitions.
type Bulb;
fn Bulb_id(bulb: &Bulb) -> String;
fn Bulb_position_bulb_group(bulb: &Bulb) -> UniquePtr<InertialPosition>;
Expand All @@ -99,10 +112,20 @@ pub mod ffi {
// We can't automatically use the name `type` as it is a reserved keyword in Rust.
fn Bulb_type(bulb: &Bulb) -> &BulbType;
fn Bulb_arrow_orientation_rad(bulb: &Bulb) -> UniquePtr<FloatWrapper>;
fn Bulb_states(bulb: &Bulb) -> UniquePtr<CxxVector<ConstBulbStateRef>>;
fn Bulb_states(bulb: &Bulb) -> UniquePtr<CxxVector<BulbState>>;
fn GetDefaultState(self: &Bulb) -> BulbState;
fn IsValidState(self: &Bulb, state: &BulbState) -> bool;
fn Bulb_bounding_box_min(bulb: &Bulb) -> UniquePtr<Vector3>;
fn Bulb_bounding_box_max(bulb: &Bulb) -> UniquePtr<Vector3>;
fn Bulb_bulb_group(bulb: &Bulb) -> *const BulbGroup;

// BulbGroup bindings definitions.
type BulbGroup;
fn BulbGroup_id(bulb_group: &BulbGroup) -> String;
fn BulbGroup_position_traffic_light(bulb_group: &BulbGroup) -> UniquePtr<InertialPosition>;
fn BulbGroup_orientation_traffic_light(bulb_group: &BulbGroup) -> UniquePtr<Rotation>;
fn BulbGroup_bulbs(bulb_group: &BulbGroup) -> UniquePtr<CxxVector<ConstBulbPtr>>;
fn BulbGroup_GetBulb(bulb_group: &BulbGroup, id: &String) -> *const Bulb;
fn BulbGroup_traffic_light(bulb_group: &BulbGroup) -> *const TrafficLight;
}
}
56 changes: 52 additions & 4 deletions maliput-sys/src/api/rules/rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,20 @@ std::unique_ptr<maliput::api::Rotation> TrafficLight_orientation_road_network(co
return std::make_unique<maliput::api::Rotation>(traffic_light.orientation_road_network());
}

std::unique_ptr<std::vector<ConstBulbGroupPtr>> TrafficLight_bulb_groups(const TrafficLight& traffic_light) {
const auto bulb_groups_cpp = traffic_light.bulb_groups();
std::vector<ConstBulbGroupPtr> bulb_groups;
bulb_groups.reserve(bulb_groups_cpp.size());
for (const auto bulb_group : bulb_groups_cpp) {
bulb_groups.push_back({bulb_group});
}
return std::make_unique<std::vector<ConstBulbGroupPtr>>(std::move(bulb_groups));
}

const BulbGroup* TrafficLight_GetBulbGroup(const TrafficLight& traffic_light, const rust::String& id) {
return traffic_light.GetBulbGroup(BulbGroup::Id{std::string(id)});
}

rust::String Bulb_id(const Bulb& bulb) {
return bulb.id().string();
}
Expand All @@ -91,14 +105,14 @@ std::unique_ptr<FloatWrapper> Bulb_arrow_orientation_rad(const Bulb& bulb) {
return orientation.has_value() ? std::make_unique<FloatWrapper>(FloatWrapper{orientation.value()}) : nullptr;
}

std::unique_ptr<std::vector<ConstBulbStateRef>> Bulb_states(const Bulb& bulb) {
std::unique_ptr<std::vector<BulbState>> Bulb_states(const Bulb& bulb) {
const auto states_cpp = bulb.states();
std::vector<ConstBulbStateRef> states;
std::vector<BulbState> states;
states.reserve(states_cpp.size());
for (const auto state : states_cpp) {
states.push_back({state});
states.push_back(state);
}
return std::make_unique<std::vector<ConstBulbStateRef>>(std::move(states));
return std::make_unique<std::vector<BulbState>>(std::move(states));
}

std::unique_ptr<maliput::math::Vector3> Bulb_bounding_box_min(const Bulb& bulb) {
Expand All @@ -109,6 +123,40 @@ std::unique_ptr<maliput::math::Vector3> Bulb_bounding_box_max(const Bulb& bulb)
return std::make_unique<maliput::math::Vector3>(bulb.bounding_box().p_BMax);
}

const BulbGroup* Bulb_bulb_group(const Bulb& bulb) {
return bulb.bulb_group();
}

rust::String BulbGroup_id(const BulbGroup& bulb_group) {
return bulb_group.id().string();
}

std::unique_ptr<InertialPosition> BulbGroup_position_traffic_light(const BulbGroup& bulb_group) {
return std::make_unique<InertialPosition>(bulb_group.position_traffic_light());
}

std::unique_ptr<Rotation> BulbGroup_orientation_traffic_light(const BulbGroup& bulb_group) {
return std::make_unique<Rotation>(bulb_group.orientation_traffic_light());
}

std::unique_ptr<std::vector<ConstBulbPtr>> BulbGroup_bulbs(const BulbGroup& bulb_group) {
const auto bulbs_cpp = bulb_group.bulbs();
std::vector<ConstBulbPtr> bulbs;
bulbs.reserve(bulbs_cpp.size());
for (const auto bulb : bulbs_cpp) {
bulbs.push_back({bulb});
}
return std::make_unique<std::vector<ConstBulbPtr>>(std::move(bulbs));
}

const Bulb* BulbGroup_GetBulb(const BulbGroup& bulb_group, const rust::String& id) {
return bulb_group.GetBulb(Bulb::Id{std::string(id)});
}

const TrafficLight* BulbGroup_traffic_light(const BulbGroup& bulb_group) {
return bulb_group.traffic_light();
}

} // namespace rules
} // namespace api
} // namespace maliput
143 changes: 137 additions & 6 deletions maliput/src/api/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,24 +108,59 @@ impl<'a> TrafficLight<'a> {
let rotation = maliput_sys::api::rules::ffi::TrafficLight_orientation_road_network(self.traffic_light);
crate::api::Rotation { r: rotation }
}
}

/// Forward declaration of the [BulbGroup] struct.
pub struct BulbGroup;
/// Get the bulb groups of the [TrafficLight].
/// ## Return
/// A vector of [BulbGroup]s in the [TrafficLight].
/// If the [TrafficLight] has no bulb groups, return an empty vector.
pub fn bulb_groups(&self) -> Vec<BulbGroup> {
let bulb_groups_cpp = maliput_sys::api::rules::ffi::TrafficLight_bulb_groups(self.traffic_light);
bulb_groups_cpp
.into_iter()
.map(|bg| BulbGroup {
bulb_group: unsafe { bg.bulb_group.as_ref().expect("") },
})
.collect::<Vec<BulbGroup>>()
}

/// Get a [BulbGroup] by its id.
/// ## Arguments
/// * `id` - The id of the [BulbGroup].
///
/// ## Return
/// The [BulbGroup] with the given id.
/// If no [BulbGroup] is found with the given id, return None.
pub fn get_bulb_group(&self, id: &String) -> Option<BulbGroup> {
let bulb_group = maliput_sys::api::rules::ffi::TrafficLight_GetBulbGroup(self.traffic_light, id);
if bulb_group.is_null() {
return None;
}
Some(BulbGroup {
bulb_group: unsafe {
bulb_group
.as_ref()
.expect("Unable to get underlying bulb group pointer")
},
})
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// Defines the possible bulb colors.
pub enum BulbColor {
Red,
Yellow,
Green,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// Defines the possible bulb types.
pub enum BulbType {
Round,
Arrow,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// Defines the possible bulb types.
pub enum BulbState {
Off,
Expand Down Expand Up @@ -207,7 +242,7 @@ impl Bulb<'_> {
let states_cpp = maliput_sys::api::rules::ffi::Bulb_states(self.bulb);
states_cpp
.into_iter()
.map(|state| Bulb::_from_cpp_state_to_rust_state(state.bulb_state))
.map(Bulb::_from_cpp_state_to_rust_state)
.collect::<Vec<BulbState>>()
}

Expand Down Expand Up @@ -235,8 +270,14 @@ impl Bulb<'_> {
/// ## Return
/// The parent [BulbGroup] of the bulb.
/// If the bulb is not part of any group, return None.
pub fn bulb_group(&self) -> Option<BulbGroup> {
unimplemented!()
pub fn bulb_group(&self) -> BulbGroup {
BulbGroup {
bulb_group: unsafe {
maliput_sys::api::rules::ffi::Bulb_bulb_group(self.bulb)
.as_ref()
.expect("Unable to get underlying bulb group pointer. The Bulb might not be part of any BulbGroup.")
},
}
}

/// Convert from the C++ BulbState to the Rust BulbState
Expand Down Expand Up @@ -272,3 +313,93 @@ impl Bulb<'_> {
}
}
}

/// Models a group of bulbs within a traffic light. All of the bulbs within a
/// group should share the same approximate orientation. However, this is not
/// programmatically enforced.
/// About the bulb group pose:
/// - The position of the bulb group is defined as the linear offset of this bulb group's frame
/// relative to the frame of the traffic light that contains it. The origin of
/// this bulb group's frame should approximate the bulb group's CoM.
/// - The orientation of the bulb group is defined as the rotational offset of this bulb
/// group's frame relative to the frame of the traffic light that contains it.
/// The +Z axis should align with the bulb group's "up" direction, and the +X
/// axis should point in the direction that the bulb group is facing.
/// Following a right-handed coordinate frame, the +Y axis should point left
/// when facing the +X direction.
pub struct BulbGroup<'a> {
pub bulb_group: &'a maliput_sys::api::rules::ffi::BulbGroup,
}

impl BulbGroup<'_> {
/// Returns this BulbGroup instance's unique identifier.
pub fn unique_id(&self) -> String {
unimplemented!()
}

/// Get the id of the [BulbGroup].
/// ## Return
/// The id of the [BulbGroup].
pub fn id(&self) -> String {
maliput_sys::api::rules::ffi::BulbGroup_id(self.bulb_group)
}

/// Get the position of the [BulbGroup] in the traffic light.
/// ## Return
/// An [crate::api::InertialPosition] representing the position of the [BulbGroup] in the traffic light.
pub fn position_traffic_light(&self) -> crate::api::InertialPosition {
let inertial_position = maliput_sys::api::rules::ffi::BulbGroup_position_traffic_light(self.bulb_group);
crate::api::InertialPosition { ip: inertial_position }
}

/// Get the orientation of the [BulbGroup] in the traffic light.
/// ## Return
/// An [crate::api::Rotation] representing the orientation of the [BulbGroup] in the traffic light.
pub fn orientation_traffic_light(&self) -> crate::api::Rotation {
let rotation = maliput_sys::api::rules::ffi::BulbGroup_orientation_traffic_light(self.bulb_group);
crate::api::Rotation { r: rotation }
}

/// Returns the bulbs in the bulb group.
/// ## Return
/// A vector of [Bulb]s in the bulb group.
pub fn bulbs(&self) -> Vec<Bulb> {
let bulbs_cpp = maliput_sys::api::rules::ffi::BulbGroup_bulbs(self.bulb_group);
bulbs_cpp
.into_iter()
.map(|b| Bulb {
bulb: unsafe { b.bulb.as_ref().expect("") },
})
.collect::<Vec<Bulb>>()
}

/// Get a [Bulb] by its id
/// ## Arguments
/// * `id` - The id of the [Bulb].
///
/// ## Return
/// The [Bulb] with the given id.
/// If no [Bulb] is found with the given id, return None.
pub fn get_bulb(&self, id: &String) -> Option<Bulb> {
let bulb = maliput_sys::api::rules::ffi::BulbGroup_GetBulb(self.bulb_group, id);
if bulb.is_null() {
return None;
}
Some(Bulb {
bulb: unsafe { bulb.as_ref().expect("Unable to get underlying bulb pointer") },
})
}

/// Returns the parent [TrafficLight] of the bulb group.
/// ## Return
/// The parent [TrafficLight] of the bulb group.
pub fn traffic_light(&self) -> TrafficLight {
TrafficLight {
traffic_light: unsafe {
maliput_sys::api::rules::ffi::BulbGroup_traffic_light(self.bulb_group)
.as_ref()
.expect("Unable to get underlying traffic light pointer. The BulbGroup might not be registered to a TrafficLight.")
},
}
}
}
Loading