Skip to main content

viam_rust_utils/ffi/spatialmath/
axis_angle.rs

1use ffi_helpers::null_pointer_check;
2use nalgebra::Quaternion;
3
4use crate::spatialmath::utils::AxisAngle;
5
6/// The FFI interface for initializing axis angles. These are
7/// R4 axis angles (meaning they are represented by the x, y, z
8/// components of an axis and an additional rotational parameter
9/// theta about that axis).
10
11/// Allocates a copy of the axis angle to the heap with a stable memory address and
12/// returns the raw pointer (for use by the FFI interface)
13fn to_raw_pointer(aa: &AxisAngle) -> *mut AxisAngle {
14    Box::into_raw(Box::new(*aa))
15}
16
17/// Free memory at the address of the axis angle pointer.
18///
19/// # Safety
20///
21/// Outer processes that work with axis angles via the FFI interface MUST remember
22/// to call this function when finished with an axis angle instance
23#[no_mangle]
24pub unsafe extern "C" fn viam_free_axis_angles_memory(ptr: *mut AxisAngle) {
25    if ptr.is_null() {
26        return;
27    }
28    let _ = Box::from_raw(ptr);
29}
30
31#[no_mangle]
32#[deprecated]
33pub unsafe extern "C" fn free_axis_angles_memory(ptr: *mut AxisAngle) {
34    viam_free_axis_angles_memory(ptr)
35}
36/// Initialize axis angle from raw components and retrieve the C pointer
37/// to its address.
38///
39/// # Safety
40///
41/// When finished with the underlying axis angle initialized by this function
42/// the caller must remember to free the axis angle memory using the
43/// free_axis_angles_memory FFI function
44#[no_mangle]
45pub extern "C" fn viam_new_axis_angle(x: f64, y: f64, z: f64, theta: f64) -> *mut AxisAngle {
46    to_raw_pointer(&AxisAngle::new(x, y, z, theta))
47}
48
49#[no_mangle]
50#[deprecated]
51pub extern "C" fn new_axis_angle(x: f64, y: f64, z: f64, theta: f64) -> *mut AxisAngle {
52    viam_new_axis_angle(x, y, z, theta)
53}
54
55/// Converts a quaternion into an R4 axis angle. The return value is a pointer
56/// to a list of [x, y, x, theta], where (x,y,z) are the axis vector components
57/// and theta is the rotation about the axis in radians. A zero quaternion returns
58/// a zero axis angle. In the event of an error from the nalgebra crate, a zero
59/// axis angle is also returned.
60///
61/// # Safety
62///
63/// When finished with the underlying quaternion passed to this function
64/// the caller must remember to free the quaternion memory using the
65/// free_quaternion_memory FFI function and the axis angle memory using
66/// the free_array_memory function
67#[no_mangle]
68pub unsafe extern "C" fn viam_axis_angle_from_quaternion(
69    quat: *const Quaternion<f64>,
70) -> *mut AxisAngle {
71    null_pointer_check!(quat);
72    let axis_angle = match (*quat).try_into() {
73        Ok(aa) => aa,
74        Err(_err) => AxisAngle::new(0.0, 0.0, 0.0, 0.0),
75    };
76    to_raw_pointer(&axis_angle)
77}
78
79#[no_mangle]
80#[deprecated]
81pub unsafe extern "C" fn axis_angle_from_quaternion(
82    quat: *const Quaternion<f64>,
83) -> *mut AxisAngle {
84    viam_axis_angle_from_quaternion(quat)
85}