CartesianTree 0.3.0

Build hierarchical Cartesian coordinate systems to easily transform poses.
Documentation
use pyo3::prelude::*;

use crate::{
    Pose as RustPose,
    bindings::{
        PyFrame,
        lazy_access::{PyLazyRotation, PyLazyTranslation},
        utils::{PyIsometry, PyRotation, PyVector3},
    },
};

#[pyclass(name = "Pose", unsendable)]
#[derive(Clone)]
pub struct PyPose {
    pub(crate) rust_pose: RustPose,
}

#[pymethods]
impl PyPose {
    fn frame(&self) -> Option<PyFrame> {
        self.rust_pose
            .frame()
            .map(|frame| PyFrame { rust_frame: frame })
    }

    fn transformation(&self) -> (PyVector3, PyRotation) {
        let isometry = self.rust_pose.transformation();
        (
            PyVector3 {
                inner: isometry.translation.vector,
            },
            PyRotation {
                rust_rotation: isometry.rotation.into(),
            },
        )
    }

    #[getter]
    const fn position(&self) -> PyVector3 {
        PyVector3 {
            inner: self.rust_pose.position(),
        }
    }

    #[getter]
    fn orientation(&self) -> PyRotation {
        PyRotation {
            rust_rotation: self.rust_pose.orientation(),
        }
    }

    #[pyo3(signature = (position, orientation))]
    fn set(&mut self, position: PyVector3, orientation: PyRotation) {
        self.rust_pose
            .set(position.inner, orientation.rust_rotation);
    }

    #[pyo3(signature = (isometry))]
    fn apply_in_parent_frame(&mut self, isometry: PyIsometry) {
        self.rust_pose.apply_in_parent_frame(&isometry.inner);
    }

    #[pyo3(signature = (isometry))]
    fn apply_in_local_frame(&mut self, isometry: PyIsometry) {
        self.rust_pose.apply_in_local_frame(&isometry.inner);
    }

    #[pyo3(signature = (target_frame))]
    fn in_frame(&self, target_frame: &PyFrame) -> PyResult<Self> {
        let new_rust_pose = self.rust_pose.in_frame(&target_frame.rust_frame)?;
        Ok(Self {
            rust_pose: new_rust_pose,
        })
    }

    fn __add__(&self, other: PyLazyTranslation) -> Self {
        let new_rust_pose = &self.rust_pose + other.inner;
        Self {
            rust_pose: new_rust_pose,
        }
    }

    fn __sub__(&self, other: PyLazyTranslation) -> Self {
        let new_rust_pose = &self.rust_pose - other.inner;
        Self {
            rust_pose: new_rust_pose,
        }
    }

    fn __mul__(&self, other: PyLazyRotation) -> Self {
        let new_rust_pose = &self.rust_pose * other.inner;
        Self {
            rust_pose: new_rust_pose,
        }
    }

    fn __str__(&self) -> String {
        let isometry = self.rust_pose.transformation();
        let vector = isometry.translation.vector;
        let quaternion = isometry.rotation.coords;
        format!(
            "({:.2}, {:.2}, {:.2})({:.4}, {:.4}, {:.4}, {:.4})",
            vector.x, vector.y, vector.z, quaternion.x, quaternion.y, quaternion.z, quaternion.w,
        )
    }

    fn __repr__(&self) -> String {
        self.__str__()
    }
}