pub struct Vector3 {
pub(crate) v: cxx::UniquePtr<maliput_sys::math::ffi::Vector3>,
}
impl Vector3 {
pub fn new(x: f64, y: f64, z: f64) -> Vector3 {
Vector3 {
v: maliput_sys::math::ffi::Vector3_new(x, y, z),
}
}
pub fn x(&self) -> f64 {
self.v.x()
}
pub fn y(&self) -> f64 {
self.v.y()
}
pub fn z(&self) -> f64 {
self.v.z()
}
pub fn norm(&self) -> f64 {
self.v.norm()
}
pub fn normalize(&mut self) {
self.v.as_mut().expect("Unexpected error").normalize();
}
pub fn dot(&self, w: &Vector3) -> f64 {
maliput_sys::math::ffi::Vector3_dot(&self.v, &w.v)
}
pub fn cross(&self, w: &Vector3) -> Vector3 {
Vector3 {
v: maliput_sys::math::ffi::Vector3_cross(&self.v, &w.v),
}
}
}
impl PartialEq for Vector3 {
fn eq(&self, other: &Self) -> bool {
maliput_sys::math::ffi::Vector3_equals(&self.v, &other.v)
}
}
impl Eq for Vector3 {}
impl std::fmt::Display for Vector3 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", maliput_sys::math::ffi::Vector3_to_str(&self.v))
}
}
impl std::fmt::Debug for Vector3 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Vector3")
.field("x", &self.x())
.field("y", &self.y())
.field("z", &self.z())
.finish()
}
}
pub struct Vector4 {
v: cxx::UniquePtr<maliput_sys::math::ffi::Vector4>,
}
impl Vector4 {
pub fn new(x: f64, y: f64, z: f64, w: f64) -> Vector4 {
Vector4 {
v: maliput_sys::math::ffi::Vector4_new(x, y, z, w),
}
}
pub fn x(&self) -> f64 {
self.v.x()
}
pub fn y(&self) -> f64 {
self.v.y()
}
pub fn z(&self) -> f64 {
self.v.z()
}
pub fn w(&self) -> f64 {
self.v.w()
}
pub fn norm(&self) -> f64 {
self.v.norm()
}
pub fn dot(&self, w: &Vector4) -> f64 {
maliput_sys::math::ffi::Vector4_dot(&self.v, &w.v)
}
pub fn normalize(&mut self) {
self.v.as_mut().expect("Unexpected error").normalize();
}
}
impl PartialEq for Vector4 {
fn eq(&self, other: &Self) -> bool {
maliput_sys::math::ffi::Vector4_equals(&self.v, &other.v)
}
}
impl Eq for Vector4 {}
impl std::fmt::Display for Vector4 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", maliput_sys::math::ffi::Vector4_to_str(&self.v))
}
}
impl std::fmt::Debug for Vector4 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Vector4")
.field("x", &self.x())
.field("y", &self.y())
.field("z", &self.z())
.field("w", &self.z())
.finish()
}
}
pub struct Matrix3 {
m: cxx::UniquePtr<maliput_sys::math::ffi::Matrix3>,
}
impl Matrix3 {
pub fn new(row1: Vector3, row2: Vector3, row3: Vector3) -> Matrix3 {
Matrix3 {
m: maliput_sys::math::ffi::Matrix3_new(
row1.x(),
row1.y(),
row1.z(),
row2.x(),
row2.y(),
row2.z(),
row3.x(),
row3.y(),
row3.z(),
),
}
}
pub fn cofactor(&self, row: usize, col: usize) -> f64 {
self.m.cofactor(row, col)
}
pub fn cofactor_matrix(&self) -> Matrix3 {
Matrix3 {
m: maliput_sys::math::ffi::Matrix3_cofactor_matrix(&self.m),
}
}
pub fn determinant(&self) -> f64 {
self.m.determinant()
}
pub fn is_singular(&self) -> bool {
self.m.is_singular()
}
pub fn row(&self, index: usize) -> Vector3 {
Vector3 {
v: maliput_sys::math::ffi::Matrix3_row(&self.m, index),
}
}
pub fn col(&self, index: usize) -> Vector3 {
Vector3 {
v: maliput_sys::math::ffi::Matrix3_col(&self.m, index),
}
}
pub fn transpose(&self) -> Matrix3 {
Matrix3 {
m: maliput_sys::math::ffi::Matrix3_transpose(&self.m),
}
}
pub fn adjoint(&self) -> Matrix3 {
Matrix3 {
m: maliput_sys::math::ffi::Matrix3_adjoint(&self.m),
}
}
pub fn inverse(&self) -> Matrix3 {
Matrix3 {
m: maliput_sys::math::ffi::Matrix3_inverse(&self.m),
}
}
}
impl PartialEq for Matrix3 {
fn eq(&self, other: &Self) -> bool {
maliput_sys::math::ffi::Matrix3_equals(&self.m, &other.m)
}
}
impl Eq for Matrix3 {}
impl std::fmt::Display for Matrix3 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", maliput_sys::math::ffi::Matrix3_to_str(&self.m))
}
}
impl std::fmt::Debug for Matrix3 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Matrix3")
.field("row1", &self.row(0))
.field("row2", &self.row(1))
.field("row3", &self.row(2))
.finish()
}
}
pub struct Quaternion {
q: cxx::UniquePtr<maliput_sys::math::ffi::Quaternion>,
}
impl Quaternion {
pub fn new(w: f64, x: f64, y: f64, z: f64) -> Quaternion {
Quaternion {
q: maliput_sys::math::ffi::Quaternion_new(w, x, y, z),
}
}
pub fn w(&self) -> f64 {
self.q.w()
}
pub fn x(&self) -> f64 {
self.q.x()
}
pub fn y(&self) -> f64 {
self.q.y()
}
pub fn z(&self) -> f64 {
self.q.z()
}
pub fn vec(&self) -> Vector3 {
Vector3 {
v: maliput_sys::math::ffi::Quaternion_vec(&self.q),
}
}
pub fn coeffs(&self) -> Vector4 {
Vector4 {
v: maliput_sys::math::ffi::Quaternion_coeffs(&self.q),
}
}
pub fn dot(&self, other: &Quaternion) -> f64 {
self.q.dot(&other.q)
}
pub fn angular_distance(&self, other: &Quaternion) -> f64 {
self.q.AngularDistance(&other.q)
}
pub fn norm(&self) -> f64 {
self.q.norm()
}
pub fn normalize(&mut self) {
self.q.as_mut().expect("Unexpected error").normalize();
}
pub fn squared_norm(&self) -> f64 {
self.q.squared_norm()
}
pub fn inverse(&self) -> Quaternion {
Quaternion {
q: maliput_sys::math::ffi::Quaternion_Inverse(&self.q),
}
}
pub fn conjugate(&self) -> Quaternion {
Quaternion {
q: maliput_sys::math::ffi::Quaternion_conjugate(&self.q),
}
}
pub fn to_rotation_matrix(&self) -> Matrix3 {
let q = maliput_sys::math::ffi::Quaternion_ToRotationMatrix(&self.q);
Matrix3 { m: q }
}
pub fn transform_vector(&self, v: &Vector3) -> Vector3 {
let q = maliput_sys::math::ffi::Quaternion_TransformVector(&self.q, &v.v);
Vector3 { v: q }
}
}
impl PartialEq for Quaternion {
fn eq(&self, other: &Self) -> bool {
maliput_sys::math::ffi::Quaternion_equals(&self.q, &other.q)
}
}
impl Eq for Quaternion {}
impl std::fmt::Display for Quaternion {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", maliput_sys::math::ffi::Quaternion_to_str(&self.q))
}
}
impl std::fmt::Debug for Quaternion {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Quaternion")
.field("w", &self.w())
.field("x", &self.x())
.field("y", &self.y())
.field("z", &self.z())
.finish()
}
}
pub struct RollPitchYaw {
rpy: cxx::UniquePtr<maliput_sys::math::ffi::RollPitchYaw>,
}
impl RollPitchYaw {
pub fn new(roll: f64, pitch: f64, yaw: f64) -> RollPitchYaw {
RollPitchYaw {
rpy: maliput_sys::math::ffi::RollPitchYaw_new(roll, pitch, yaw),
}
}
pub fn roll_angle(&self) -> f64 {
self.rpy.roll_angle()
}
pub fn pitch_angle(&self) -> f64 {
self.rpy.pitch_angle()
}
pub fn yaw_angle(&self) -> f64 {
self.rpy.yaw_angle()
}
pub fn vector(&self) -> Vector3 {
Vector3::new(self.rpy.vector().x(), self.rpy.vector().y(), self.rpy.vector().z())
}
pub fn set(&mut self, roll: f64, pitch: f64, yaw: f64) {
maliput_sys::math::ffi::RollPitchYaw_set(self.rpy.as_mut().expect("Unexpected Error"), roll, pitch, yaw);
}
pub fn set_from_quaternion(&mut self, q: &Quaternion) {
maliput_sys::math::ffi::RollPitchYaw_SetFromQuaternion(self.rpy.as_mut().expect("Unexpected Error"), &q.q);
}
pub fn to_quaternion(&self) -> Quaternion {
Quaternion {
q: maliput_sys::math::ffi::RollPitchYaw_ToQuaternion(&self.rpy),
}
}
pub fn to_matrix(&self) -> Matrix3 {
Matrix3 {
m: maliput_sys::math::ffi::RollPitchYaw_ToMatrix(&self.rpy),
}
}
pub fn calc_rotation_matrix_dt(&self, rpy_dt: &Vector3) -> Matrix3 {
Matrix3 {
m: maliput_sys::math::ffi::RollPitchYaw_CalcRotationMatrixDt(&self.rpy, &rpy_dt.v),
}
}
}
pub struct BoundingBox {
pub(crate) b: cxx::UniquePtr<maliput_sys::math::ffi::BoundingBox>,
}
impl BoundingBox {
pub fn new(position: &Vector3, box_size: &Vector3, orientation: &RollPitchYaw, tolerance: f64) -> BoundingBox {
BoundingBox {
b: maliput_sys::math::ffi::BoundingBox_new(&position.v, &box_size.v, &orientation.rpy, tolerance),
}
}
pub fn position(&self) -> Vector3 {
let p = maliput_sys::math::ffi::BoundingBox::position(&self.b);
Vector3::new(p.x(), p.y(), p.z())
}
pub fn box_size(&self) -> Vector3 {
let s = maliput_sys::math::ffi::BoundingBox::box_size(&self.b);
Vector3::new(s.x(), s.y(), s.z())
}
pub fn orientation(&self) -> RollPitchYaw {
let r = maliput_sys::math::ffi::BoundingBox::get_orientation(&self.b);
RollPitchYaw::new(r.roll_angle(), r.pitch_angle(), r.yaw_angle())
}
pub fn get_vertices(&self) -> Vec<Vector3> {
let verts = maliput_sys::math::ffi::BoundingBox_get_vertices(&self.b);
verts.iter().map(|v| Vector3::new(v.x(), v.y(), v.z())).collect()
}
pub fn is_box_contained(&self, other: &BoundingBox) -> bool {
maliput_sys::math::ffi::BoundingBox::IsBoxContained(&self.b, &other.b)
}
pub fn is_box_intersected(&self, other: &BoundingBox) -> bool {
maliput_sys::math::ffi::BoundingBox::IsBoxIntersected(&self.b, &other.b)
}
}
mod tests {
#[test]
fn vector3_new() {
let v = super::Vector3::new(1.0, 2.0, 3.0);
assert_eq!(v.x(), 1.0);
assert_eq!(v.y(), 2.0);
assert_eq!(v.z(), 3.0);
}
#[test]
fn vector3_equality() {
let v = super::Vector3::new(1.0, 2.0, 3.0);
let w = super::Vector3::new(1.0, 2.0, 3.0);
assert_eq!(v, w);
let z = super::Vector3::new(4.0, 5.0, 6.0);
assert_ne!(v, z);
}
#[test]
fn vector3_norm() {
let v = super::Vector3::new(1.0, 2.0, 3.0);
assert_eq!(v.norm(), (v.x() * v.x() + v.y() * v.y() + v.z() * v.z()).sqrt());
}
#[test]
fn vector3_normalize() {
let mut v = super::Vector3::new(1.0, 2.0, 3.0);
let norm = v.norm();
v.normalize();
assert_eq!(v.x(), 1.0 / norm);
assert_eq!(v.y(), 2.0 / norm);
assert_eq!(v.z(), 3.0 / norm);
}
#[test]
fn vector3_dot() {
let v = super::Vector3::new(1.0, 2.0, 3.0);
let w = super::Vector3::new(4.0, 5.0, 6.0);
assert_eq!(v.dot(&w), v.x() * w.x() + v.y() * w.y() + v.z() * w.z());
}
#[test]
fn vector3_cross() {
let v = super::Vector3::new(1.0, 2.0, 3.0);
let w = super::Vector3::new(4.0, 5.0, 6.0);
let cross = v.cross(&w);
assert_eq!(cross.x(), v.y() * w.z() - v.z() * w.y());
assert_eq!(cross.y(), v.z() * w.x() - v.x() * w.z());
assert_eq!(cross.z(), v.x() * w.y() - v.y() * w.x());
}
#[test]
fn vector4_new() {
let v = super::Vector4::new(1.0, 2.0, 3.0, 4.0);
assert_eq!(v.x(), 1.0);
assert_eq!(v.y(), 2.0);
assert_eq!(v.z(), 3.0);
assert_eq!(v.w(), 4.0);
}
#[test]
fn vector4_equality() {
let v = super::Vector4::new(1.0, 2.0, 3.0, 4.0);
let w = super::Vector4::new(1.0, 2.0, 3.0, 4.0);
assert_eq!(v, w);
let z = super::Vector4::new(4.0, 5.0, 6.0, 7.0);
assert_ne!(v, z);
}
#[test]
fn vector4_norm() {
let v = super::Vector4::new(1.0, 2.0, 3.0, 4.0);
assert_eq!(
v.norm(),
(v.x() * v.x() + v.y() * v.y() + v.z() * v.z() + v.w() * v.w()).sqrt()
);
}
#[test]
fn vector4_dot() {
let v = super::Vector4::new(1.0, 2.0, 3.0, 4.0);
let w = super::Vector4::new(4.0, 5.0, 6.0, 7.0);
assert_eq!(v.dot(&w), v.x() * w.x() + v.y() * w.y() + v.z() * w.z() + v.w() * w.w());
}
#[test]
fn vector4_normalize() {
let mut v = super::Vector4::new(1.0, 2.0, 3.0, 4.0);
let norm = v.norm();
v.normalize();
assert_eq!(v.x(), 1.0 / norm);
assert_eq!(v.y(), 2.0 / norm);
assert_eq!(v.z(), 3.0 / norm);
assert_eq!(v.w(), 4.0 / norm);
}
#[test]
fn matrix4_tests() {
let row_1 = super::Vector3::new(1.0, 2.0, 3.0);
let row_2 = super::Vector3::new(4.0, 5.0, 6.0);
let row_3 = super::Vector3::new(7.0, 8.0, 9.0);
let _m = super::Matrix3::new(row_1, row_2, row_3);
assert_eq!(_m.row(0).x(), 1.0);
assert_eq!(_m.col(2).z(), 9.0);
}
#[test]
fn quaternion_tests() {
let q = super::Quaternion::new(1.0, 2.0, 3.0, 4.0);
assert_eq!(q.w(), 1.0);
assert_eq!(q.x(), 2.0);
assert_eq!(q.y(), 3.0);
assert_eq!(q.z(), 4.0);
}
#[test]
fn roll_pitch_yaw_tests() {
let rpy = super::RollPitchYaw::new(1.0, 2.0, 3.0);
assert_eq!(rpy.roll_angle(), 1.0);
assert_eq!(rpy.pitch_angle(), 2.0);
assert_eq!(rpy.yaw_angle(), 3.0);
}
#[test]
fn bounding_box_new() {
let position = super::Vector3::new(1.0, 2.0, 3.0);
let box_size = super::Vector3::new(4.0, 5.0, 6.0);
let orientation = super::RollPitchYaw::new(0.1, 0.2, 0.3);
let tolerance = 1e-3;
let bb = super::BoundingBox::new(&position, &box_size, &orientation, tolerance);
assert_eq!(bb.position().x(), 1.0);
assert_eq!(bb.position().y(), 2.0);
assert_eq!(bb.position().z(), 3.0);
assert_eq!(bb.box_size().x(), 4.0);
assert_eq!(bb.box_size().y(), 5.0);
assert_eq!(bb.box_size().z(), 6.0);
assert_eq!(bb.orientation().roll_angle(), 0.1);
assert_eq!(bb.orientation().pitch_angle(), 0.2);
assert_eq!(bb.orientation().yaw_angle(), 0.3);
}
#[test]
fn bounding_box_position() {
let position = super::Vector3::new(1.0, 2.0, 3.0);
let box_size = super::Vector3::new(4.0, 5.0, 6.0);
let orientation = super::RollPitchYaw::new(0.0, 0.0, 0.0);
let bb = super::BoundingBox::new(&position, &box_size, &orientation, 1e-3);
assert_eq!(bb.position().x(), 1.0);
assert_eq!(bb.position().y(), 2.0);
assert_eq!(bb.position().z(), 3.0);
}
#[test]
fn bounding_box_box_size() {
let position = super::Vector3::new(0.0, 0.0, 0.0);
let box_size = super::Vector3::new(4.0, 5.0, 6.0);
let orientation = super::RollPitchYaw::new(0.0, 0.0, 0.0);
let bb = super::BoundingBox::new(&position, &box_size, &orientation, 1e-3);
assert_eq!(bb.box_size().x(), 4.0);
assert_eq!(bb.box_size().y(), 5.0);
assert_eq!(bb.box_size().z(), 6.0);
}
#[test]
fn bounding_box_orientation() {
let position = super::Vector3::new(0.0, 0.0, 0.0);
let box_size = super::Vector3::new(1.0, 1.0, 1.0);
let orientation = super::RollPitchYaw::new(0.1, 0.2, 0.3);
let bb = super::BoundingBox::new(&position, &box_size, &orientation, 1e-3);
assert_eq!(bb.orientation().roll_angle(), 0.1);
assert_eq!(bb.orientation().pitch_angle(), 0.2);
assert_eq!(bb.orientation().yaw_angle(), 0.3);
}
#[test]
fn bounding_box_get_vertices() {
let position = super::Vector3::new(0.0, 0.0, 0.0);
let box_size = super::Vector3::new(2.0, 2.0, 2.0);
let orientation = super::RollPitchYaw::new(0.0, 0.0, 0.0);
let bb = super::BoundingBox::new(&position, &box_size, &orientation, 1e-3);
let vertices = bb.get_vertices();
assert_eq!(vertices.len(), 8);
}
#[test]
fn bounding_box_is_box_contained() {
let origin = super::Vector3::new(0.0, 0.0, 0.0);
let identity = super::RollPitchYaw::new(0.0, 0.0, 0.0);
let big_box = super::BoundingBox::new(&origin, &super::Vector3::new(10.0, 10.0, 10.0), &identity, 1e-3);
let small_box = super::BoundingBox::new(&origin, &super::Vector3::new(1.0, 1.0, 1.0), &identity, 1e-3);
assert!(big_box.is_box_contained(&small_box));
assert!(!small_box.is_box_contained(&big_box));
}
#[test]
fn bounding_box_is_box_intersected() {
let identity = super::RollPitchYaw::new(0.0, 0.0, 0.0);
let box_a = super::BoundingBox::new(
&super::Vector3::new(0.0, 0.0, 0.0),
&super::Vector3::new(2.0, 2.0, 2.0),
&identity,
1e-3,
);
let box_b = super::BoundingBox::new(
&super::Vector3::new(1.0, 0.0, 0.0),
&super::Vector3::new(2.0, 2.0, 2.0),
&identity,
1e-3,
);
let box_c = super::BoundingBox::new(
&super::Vector3::new(100.0, 0.0, 0.0),
&super::Vector3::new(2.0, 2.0, 2.0),
&identity,
1e-3,
);
assert!(box_a.is_box_intersected(&box_b));
assert!(!box_a.is_box_intersected(&box_c));
}
}