viam_rust_utils/ffi/spatialmath/
euler_angles.rs

1use ffi_helpers::null_pointer_check;
2use nalgebra::Quaternion;
3
4use crate::spatialmath::utils::EulerAngles;
5
6/// The FFI interface for initializing euler angles. Our euler angles
7/// follow the Tait-Bryan formalism and are applied in the Z-Y'-X" order
8/// (where Z -> yaw, Y -> pitch, X -> roll).
9///
10/// It is highly recommended not to attempt any mathematics with the euler
11/// angles directly and to convert to quaternions via the FFI interface instead
12
13/// Allocates a copy of the euler angles to the heap with a stable memory address and
14/// returns the raw pointer (for use by the FFI interface)
15fn to_raw_pointer(ea: &EulerAngles) -> *mut EulerAngles {
16    Box::into_raw(Box::new(*ea))
17}
18
19/// Free memory at the address of the euler angles pointer.
20///
21/// # Safety
22///
23/// Outer processes that work with EulerAngles via the FFI interface MUST remember
24/// to call this function when finished with a euler angles instance
25#[no_mangle]
26pub unsafe extern "C" fn free_euler_angles_memory(ptr: *mut EulerAngles) {
27    if ptr.is_null() {
28        return;
29    }
30    let _ = Box::from_raw(ptr);
31}
32
33/// Initialize euler angles from raw components and retrieve the C pointer
34/// to its address.
35///
36/// # Safety
37///
38/// When finished with the underlying euler angles initialized by this function
39/// the caller must remember to free the euler angles memory using the
40/// free_euler_angles_memory FFI function
41#[no_mangle]
42pub extern "C" fn new_euler_angles(roll: f64, pitch: f64, yaw: f64) -> *mut EulerAngles {
43    to_raw_pointer(&EulerAngles::new(roll, pitch, yaw))
44}
45
46/// Converts a quaternion into euler angles (in radians). The euler angles are
47/// represented according to the Tait-Bryan formalism and applied
48/// in the Z-Y'-X" order (where Z -> yaw, Y -> pitch, X -> roll).
49///
50/// # Safety
51///
52/// When finished with the underlying quaternion passed to this function
53/// the caller must remember to free the quaternion memory using the
54/// free_quaternion_memory FFI function and the euler angles memory using
55/// the free_euler_angles_memory function
56#[no_mangle]
57pub unsafe extern "C" fn euler_angles_from_quaternion(
58    quat_ptr: *const Quaternion<f64>,
59) -> *mut EulerAngles {
60    null_pointer_check!(quat_ptr);
61    let euler_angles: EulerAngles = (*quat_ptr).into();
62    to_raw_pointer(&euler_angles)
63}