realsense_rust/frame/
motion.rs1use super::prelude::{CouldNotGetFrameSensorError, FrameCategory, FrameConstructionError, FrameEx};
9use crate::{
10 check_rs2_error,
11 kind::{Rs2Extension, Rs2FrameMetadata, Rs2StreamKind, Rs2TimestampDomain},
12 sensor::Sensor,
13 stream_profile::StreamProfile,
14};
15use anyhow::Result;
16use num_traits::FromPrimitive;
17use realsense_sys as sys;
18use std::{
19 convert::{TryFrom, TryInto},
20 marker::PhantomData,
21 ptr::{self, NonNull},
22};
23
24#[derive(Debug)]
26pub struct Accel;
27#[derive(Debug)]
29pub struct Gyro;
30
31#[derive(Debug)]
37pub struct MotionFrame<Kind> {
38 frame_ptr: NonNull<sys::rs2_frame>,
40 timestamp: f64,
42 timestamp_domain: Rs2TimestampDomain,
44 frame_number: u64,
46 frame_stream_profile: StreamProfile,
48 motion: [f32; 3],
52 should_drop: bool,
55 _phantom: PhantomData<Kind>,
57}
58
59pub type AccelFrame = MotionFrame<Accel>;
61pub type GyroFrame = MotionFrame<Gyro>;
63
64impl FrameCategory for AccelFrame {
65 fn extension() -> Rs2Extension {
66 Rs2Extension::MotionFrame
67 }
68
69 fn kind() -> Rs2StreamKind {
70 Rs2StreamKind::Accel
71 }
72
73 fn has_correct_kind(&self) -> bool {
74 self.frame_stream_profile.kind() == Self::kind()
75 }
76}
77
78impl FrameCategory for GyroFrame {
79 fn extension() -> Rs2Extension {
80 Rs2Extension::MotionFrame
81 }
82
83 fn kind() -> Rs2StreamKind {
84 Rs2StreamKind::Gyro
85 }
86
87 fn has_correct_kind(&self) -> bool {
88 self.frame_stream_profile.kind() == Self::kind()
89 }
90}
91
92impl<K> Drop for MotionFrame<K> {
93 fn drop(&mut self) {
95 unsafe {
96 if self.should_drop {
97 sys::rs2_release_frame(self.frame_ptr.as_ptr());
98 }
99 }
100 }
101}
102
103unsafe impl<K> Send for MotionFrame<K> {}
104
105impl<K> TryFrom<NonNull<sys::rs2_frame>> for MotionFrame<K> {
106 type Error = anyhow::Error;
107
108 fn try_from(frame_ptr: NonNull<sys::rs2_frame>) -> Result<Self, Self::Error> {
125 unsafe {
126 let mut err = ptr::null_mut::<sys::rs2_error>();
127
128 let timestamp = sys::rs2_get_frame_timestamp(frame_ptr.as_ptr(), &mut err);
129 check_rs2_error!(err, FrameConstructionError::CouldNotGetTimestamp)?;
130
131 let timestamp_domain =
132 sys::rs2_get_frame_timestamp_domain(frame_ptr.as_ptr(), &mut err);
133 check_rs2_error!(err, FrameConstructionError::CouldNotGetTimestampDomain)?;
134
135 let frame_number = sys::rs2_get_frame_number(frame_ptr.as_ptr(), &mut err);
136 check_rs2_error!(err, FrameConstructionError::CouldNotGetFrameNumber)?;
137
138 let profile_ptr = sys::rs2_get_frame_stream_profile(frame_ptr.as_ptr(), &mut err);
139 check_rs2_error!(err, FrameConstructionError::CouldNotGetFrameStreamProfile)?;
140
141 let nonnull_profile_ptr =
142 NonNull::new(profile_ptr as *mut sys::rs2_stream_profile).unwrap();
143 let profile = StreamProfile::try_from(nonnull_profile_ptr)?;
144
145 let size = sys::rs2_get_frame_data_size(frame_ptr.as_ptr(), &mut err);
146 check_rs2_error!(err, FrameConstructionError::CouldNotGetDataSize)?;
147
148 let ptr = sys::rs2_get_frame_data(frame_ptr.as_ptr(), &mut err);
149 check_rs2_error!(err, FrameConstructionError::CouldNotGetData)?;
150
151 let data_as_ptr = ptr.as_ref().unwrap() as *const std::os::raw::c_void;
152 let data_size_in_f32s = (size as usize) / std::mem::size_of::<f32>();
153
154 let motion_raw =
155 std::slice::from_raw_parts(data_as_ptr.cast::<f32>(), data_size_in_f32s);
156
157 Ok(MotionFrame {
158 frame_ptr,
159 timestamp,
160 timestamp_domain: Rs2TimestampDomain::from_i32(timestamp_domain as i32).unwrap(),
161 frame_number,
162 frame_stream_profile: profile,
163 motion: [motion_raw[0], motion_raw[1], motion_raw[2]],
164 should_drop: true,
165 _phantom: PhantomData::<K> {},
166 })
167 }
168 }
169}
170
171impl<K> FrameEx for MotionFrame<K> {
172 fn stream_profile(&self) -> &StreamProfile {
173 &self.frame_stream_profile
174 }
175
176 fn sensor(&self) -> Result<Sensor> {
177 unsafe {
178 let mut err = std::ptr::null_mut::<sys::rs2_error>();
179 let sensor_ptr = sys::rs2_get_frame_sensor(self.frame_ptr.as_ptr(), &mut err);
180 check_rs2_error!(err, CouldNotGetFrameSensorError)?;
181
182 Ok(Sensor::from(NonNull::new(sensor_ptr).unwrap()))
183 }
184 }
185 fn timestamp(&self) -> f64 {
186 self.timestamp
187 }
188
189 fn timestamp_domain(&self) -> Rs2TimestampDomain {
190 self.timestamp_domain
191 }
192
193 fn frame_number(&self) -> u64 {
194 self.frame_number
195 }
196
197 fn metadata(&self, metadata_kind: Rs2FrameMetadata) -> Option<std::os::raw::c_longlong> {
198 if !self.supports_metadata(metadata_kind) {
199 return None;
200 }
201
202 unsafe {
203 let mut err = std::ptr::null_mut::<sys::rs2_error>();
204
205 let val = sys::rs2_get_frame_metadata(
206 self.frame_ptr.as_ptr(),
207 #[allow(clippy::useless_conversion)]
208 (metadata_kind as i32).try_into().unwrap(),
209 &mut err,
210 );
211 if err.as_ref().is_none() {
212 Some(val)
213 } else {
214 sys::rs2_free_error(err);
215 None
216 }
217 }
218 }
219
220 fn supports_metadata(&self, metadata_kind: Rs2FrameMetadata) -> bool {
221 unsafe {
222 let mut err = std::ptr::null_mut::<sys::rs2_error>();
223
224 let supports_metadata = sys::rs2_supports_frame_metadata(
225 self.frame_ptr.as_ptr(),
226 #[allow(clippy::useless_conversion)]
227 (metadata_kind as i32).try_into().unwrap(),
228 &mut err,
229 );
230
231 if err.as_ref().is_none() {
232 supports_metadata != 0
233 } else {
234 sys::rs2_free_error(err);
235 false
236 }
237 }
238 }
239
240 unsafe fn get_owned_raw(mut self) -> NonNull<sys::rs2_frame> {
241 self.should_drop = false;
242
243 self.frame_ptr
244 }
245}
246
247impl AccelFrame {
248 pub fn acceleration(&self) -> &[f32; 3] {
271 &self.motion
272 }
273}
274
275impl GyroFrame {
276 pub fn rotational_velocity(&self) -> &[f32; 3] {
299 &self.motion
300 }
301}
302
303#[cfg(test)]
304mod tests {
305 use super::*;
306
307 #[test]
308 fn frame_has_correct_kind() {
309 assert_eq!(AccelFrame::kind(), Rs2StreamKind::Accel);
310 assert_eq!(GyroFrame::kind(), Rs2StreamKind::Gyro);
311 }
312}