1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//! Common types and functions.

use crate::kind::Rs2DistortionModel;
use num_traits::FromPrimitive;
use realsense_sys as sys;
use std::{ffi::CString, time::Duration};

pub const DEFAULT_TIMEOUT: Duration = Duration::from_millis(sys::RS2_DEFAULT_TIMEOUT as u64);

// Thanks, Tenders McChiken.
// https://stackoverflow.com/questions/38948669/whats-the-most-direct-way-to-convert-a-path-to-a-c-char
pub(crate) fn from_path<P>(path: P) -> anyhow::Result<CString>
where
    P: AsRef<std::path::Path>,
{
    let mut buf = Vec::new();

    #[cfg(unix)]
    {
        use std::os::unix::ffi::OsStrExt;
        buf.extend(path.as_ref().as_os_str().as_bytes());
        buf.push(0);
    };

    #[cfg(windows)]
    {
        use std::os::windows::ffi::OsStrExt;
        buf.extend(
            path.as_ref()
                .as_os_str()
                .encode_wide()
                .chain(Some(0))
                .map(|b| {
                    let b = b.to_ne_bytes();
                    b.get(0).copied().into_iter().chain(b.get(1).copied())
                })
                .flatten(),
        );
    };

    Ok(CString::new(buf)?)
}

#[derive(Debug)]
pub struct Rs2MotionDeviceIntrinsics(pub sys::rs2_motion_device_intrinsic);

/// Profile the scale, bias, and variances for a given motion device
///
/// The bias and scale factors are stored as one large matrix; see the documentation on `data()` for the correct way to
/// retrieve these parameters.
///
/// Use the function `stream_profile.motion_intrinsics()` to retrieve these intrinsics from a certain stream.
impl Rs2MotionDeviceIntrinsics {
    /// A 3x4 matrix describing the scale and bias intrinsics of the motion device.
    ///
    /// This matrix is stored internally like so:
    /// [ Scale X    | cross axis  | cross axis | Bias X ]
    /// [ cross axis | Scale Y     | cross axis | Bias Y ]
    /// [ cross axis | cross axis  | Scale Z    | Bias Z ]
    ///
    pub fn data(&self) -> [[f32; 4usize]; 3usize] {
        self.0.data
    }
    /// Variance of noise for X, Y, and Z axis.
    pub fn noise_variances(&self) -> [f32; 3usize] {
        self.0.noise_variances
    }
    /// Variance of bias for X, Y, and Z axis.
    pub fn bias_variances(&self) -> [f32; 3usize] {
        self.0.bias_variances
    }
}

unsafe impl Send for Rs2MotionDeviceIntrinsics {}

/// Type representing the intrinsic scale, bias, and variances for a given motion device.
///
/// The data in `coeffs` means different things for different models.
///
/// - Brown-Conrady: [k1, k2, p1, p2, k3].
/// - F-Theta Fisheye: [k1, k2, k3, k4, 0].
/// - Kannala-Brandt: [k1, k2, k3, k4, 0].
///
/// The Intel RealSense documentation claims that "Other models are subject to their own interpretations". This is
/// admittedly not too helpful, but it's worth noting in case your model isn't covered here.
#[derive(Debug)]
pub struct Rs2Distortion {
    /// Distortion model of the image.
    pub model: Rs2DistortionModel,
    /// Distortion coefficients.
    pub coeffs: [f32; 5usize],
}

unsafe impl Send for Rs2Distortion {}

/// Type representing the model for describing the way that light bends in a stream.
///
/// This stores the focal length, principal point, dimensions, and distortion model used on the image frame. See the
/// documentation for [Rs2Distortion] for specifics on the available distortion models for RealSense devices.
///
/// Use the function `stream_profile.intrinsics()` to retrieve these intrinsics from a certain stream.
#[derive(Debug)]
pub struct Rs2Intrinsics(pub sys::rs2_intrinsics);

impl Rs2Intrinsics {
    /// Width of the image in pixels
    pub fn width(&self) -> usize {
        self.0.width as usize
    }
    /// Height of the image in pixels
    pub fn height(&self) -> usize {
        self.0.height as usize
    }

    /// Horizontal coordinate of the principal point of the image, as a pixel offset from the left edge
    pub fn ppx(&self) -> f32 {
        self.0.ppx
    }
    /// Vertical coordinate of the principal point of the image, as a pixel offset from the top edge
    pub fn ppy(&self) -> f32 {
        self.0.ppy
    }
    /// Focal length of the image plane, as a multiple of pixel width
    pub fn fx(&self) -> f32 {
        self.0.fx
    }
    /// Focal length of the image plane, as a multiple of pixel height
    pub fn fy(&self) -> f32 {
        self.0.fy
    }
    /// Distortion model and coefficients of the image
    pub fn distortion(&self) -> Rs2Distortion {
        Rs2Distortion {
            model: Rs2DistortionModel::from_i32(self.0.model as i32).unwrap(),
            coeffs: self.0.coeffs,
        }
    }
}

unsafe impl Send for Rs2Intrinsics {}

/// The topology describing how the different devices are oriented.
///
/// Use the function `stream_profile.extrinsics()` to retrieve these extrinsics from a certain stream in relation to
/// another stream on the same device.
#[derive(Debug)]
pub struct Rs2Extrinsics(pub sys::rs2_extrinsics);

impl Rs2Extrinsics {
    /// Column-major 3x3 rotation matrix
    pub fn rotation(&self) -> [f32; 9usize] {
        self.0.rotation
    }
    /// Three-element translation vector, in meters
    pub fn translation(&self) -> [f32; 3usize] {
        self.0.translation
    }
}

unsafe impl Send for Rs2Extrinsics {}