vzense_rust/scepter/
frame.rs

1//! Reading frames, retrieving data.
2
3use crate::{
4    red,
5    util::{new_fixed_vec, normalize_u16_to_u8},
6};
7
8use super::{device::Device, get_message};
9use std::iter::zip;
10use sys::ScStatus_SC_OK as OK;
11use vzense_sys::scepter as sys;
12
13/// Captures the next image frame from `device`. This function must be called before getting frame data using `get_..._frame()`. `max_wait_time_ms` is the maximum waiting time for the next frame in milliseconds. The recommended value is 2000 / fps.
14pub fn read_next_frame(device: &mut Device, max_wait_time_ms: u16) -> i32 {
15    unsafe {
16        let status = sys::scGetFrameReady(device.handle, max_wait_time_ms, &mut device.frame_ready);
17        if status != OK {
18            println!(
19                "{}",
20                red!(
21                    "vzense_rust: read_next_frame failed with status {}",
22                    get_message(status)
23                )
24            );
25            return status;
26        }
27    }
28    0
29}
30
31/// Raw depth data in mm as `u16`.
32pub fn get_depth_mm_u16_frame(device: &mut Device, depth_mm: &mut [u16]) {
33    if device.frame_ready.depth() == 1 {
34        let status = unsafe {
35            sys::scGetFrame(
36                device.handle,
37                sys::ScFrameType_SC_DEPTH_FRAME,
38                &mut device.frame,
39            )
40        };
41        check_frame(device, status);
42        get_u16_data(device, depth_mm);
43
44        device.current_frame_is_depth = true;
45    }
46}
47
48/// Depth data scaled according to `device.min_depth_mm` = 0 and `device.max_depth_mm` = 255 stored in a `u8` array.
49pub fn get_depth_scaled_u8_frame(device: &mut Device, depth_scaled: &mut [u8]) {
50    if device.frame_ready.depth() == 1 {
51        let status = unsafe {
52            sys::scGetFrame(
53                device.handle,
54                sys::ScFrameType_SC_DEPTH_FRAME,
55                &mut device.frame,
56            )
57        };
58        check_frame(device, status);
59        let mut depth_mm = new_fixed_vec(depth_scaled.len(), 0);
60
61        get_u16_data(device, &mut depth_mm);
62
63        normalize_u16_to_u8(
64            &depth_mm,
65            device.min_depth_mm,
66            device.max_depth_mm,
67            depth_scaled,
68        );
69        device.current_frame_is_depth = true;
70    }
71}
72
73/// Raw IR data as `u8`.
74pub fn get_ir_frame(device: &mut Device, ir: &mut [u8]) {
75    if device.frame_ready.ir() == 1 {
76        let status = unsafe {
77            sys::scGetFrame(
78                device.handle,
79                sys::ScFrameType_SC_IR_FRAME,
80                &mut device.frame,
81            )
82        };
83        check_frame(device, status);
84        get_u8_data(device, ir);
85        device.current_frame_is_depth = false;
86    }
87}
88
89/// Color data as 24 bit stored in consecutive `u8`.
90pub fn get_color_frame(device: &mut Device, color: &mut [u8]) {
91    let frame_type = if device.color_is_mapped && device.frame_ready.transformedColor() == 1 {
92        sys::ScFrameType_SC_TRANSFORM_COLOR_IMG_TO_DEPTH_SENSOR_FRAME
93    } else if !device.color_is_mapped && device.frame_ready.color() == 1 {
94        sys::ScFrameType_SC_COLOR_FRAME
95    } else {
96        return;
97    };
98    let status = unsafe { sys::scGetFrame(device.handle, frame_type, &mut device.frame) };
99    check_frame(device, status);
100    get_u8_data(device, color);
101    device.current_frame_is_depth = false;
102}
103
104fn get_u16_data(device: &Device, data: &mut [u16]) {
105    let p = unsafe {
106        std::ptr::slice_from_raw_parts(device.frame.pFrameData, device.frame.dataLen as usize)
107            .as_ref()
108            .unwrap()
109    };
110    for (di, pi) in zip(data, p.chunks_exact(2)) {
111        // create one u16 from two consecutive u8 values
112        *di = u16::from_le_bytes([pi[0], pi[1]]);
113    }
114}
115
116fn get_u8_data(device: &Device, data: &mut [u8]) {
117    unsafe {
118        let p =
119            std::ptr::slice_from_raw_parts(device.frame.pFrameData, device.frame.dataLen as usize)
120                .as_ref()
121                .unwrap();
122
123        if data.len() == (*p).len() {
124            data.copy_from_slice(p);
125        }
126    }
127}
128
129/// Check status of `scGetFrame()` and if data pointer is null.
130fn check_frame(device: &Device, status: sys::ScStatus) {
131    if status != OK {
132        panic!(
133            "{}",
134            red!("get_frame failed with status {}", get_message(status))
135        );
136    }
137    if device.frame.pFrameData.is_null() {
138        panic!("{}", red!("frame pointer is NULL!"));
139    }
140}