pub struct PoseStream { /* private fields */ }Expand description
A live pose stream from one Enpose tracker device.
Dropping a PoseStream automatically disconnects it (see
PoseStream::disconnect).
Implementations§
Source§impl PoseStream
impl PoseStream
Sourcepub fn from_ip(ip: IpAddr, create_thread: bool) -> Result<Self>
pub fn from_ip(ip: IpAddr, create_thread: bool) -> Result<Self>
Connect a pose stream to the device at ip.
ip must be IPv4 — the Enpose API is IPv4-only. An IPv6 address is
rejected with io::ErrorKind::Unsupported.
When create_thread is true, spawns the background receiver thread
described in the module docs.
§Errors
Returns an io::Error if ip is not IPv4, or if the connection to
the device cannot be established.
Sourcepub fn from_device(device: &DeviceInfo, create_thread: bool) -> Result<Self>
pub fn from_device(device: &DeviceInfo, create_thread: bool) -> Result<Self>
Connect a pose stream to a device discovered via
crate::DeviceDiscovery.
Convenience wrapper around Self::from_ip using DeviceInfo::ip.
Examples found in repository?
20fn main() -> std::io::Result<()> {
21 let devices = DeviceDiscovery::new().discover()?;
22
23 if devices.is_empty() {
24 println!("No Enpose devices found on the local network.");
25 return Ok(());
26 }
27
28 println!("Found {} device(s):", devices.len());
29 for device in &devices {
30 let status = if device.compatible {
31 "compatible"
32 } else {
33 "INCOMPATIBLE (protocol version mismatch)"
34 };
35 println!(" - {} (serial {}): {}", device.ip, device.serial, status);
36 }
37
38 // Pick the first compatible device to stream from.
39 let Some(device) = devices.iter().find(|d| d.compatible) else {
40 println!("No compatible device to stream poses from.");
41 return Ok(());
42 };
43
44 println!("\nStreaming poses from {} for {:?}...", device.ip, STREAM_DURATION);
45
46 // Threaded mode: a background thread receives and buffers poses, so none
47 // are missed regardless of how often we poll below.
48 let mut stream = PoseStream::from_device(device, true)?;
49
50 let start = Instant::now();
51 while start.elapsed() < STREAM_DURATION {
52 // Blocking receive: waits up to 3 s for a pose update, so no manual
53 // polling delay is needed.
54 for pose in stream.receive_pose_updates(true)? {
55 println!(
56 " t={:>10}us marker {:>3}: pos=({:+.4}, {:+.4}, {:+.4}) rmse={:.4} sensors={}",
57 pose.timestamp,
58 pose.marker_id,
59 pose.x,
60 pose.y,
61 pose.z,
62 pose.position_rmse,
63 pose.sensors,
64 );
65 }
66 }
67
68 // `stream` is dropped here, which disconnects from the device.
69 Ok(())
70}Sourcepub fn receive_pose_updates(&mut self, block: bool) -> Result<Vec<MarkerPose>>
pub fn receive_pose_updates(&mut self, block: bool) -> Result<Vec<MarkerPose>>
Return the marker poses received from the stream.
When block is false, returns all poses that have arrived since the
previous call, or an empty vector if none have — it never waits. When
block is true, it waits for a pose update and returns the poses
gathered so far; the wait is bounded by a 3-second timeout, so a
blocking call still returns an empty vector if no update arrives within
that window.
Call it repeatedly to keep receiving updates. In threaded mode the poses are those gathered by the background thread.
§Errors
Returns an io::Error only for an unrecoverable communication
failure. In threaded mode this never returns an error.
Examples found in repository?
20fn main() -> std::io::Result<()> {
21 let devices = DeviceDiscovery::new().discover()?;
22
23 if devices.is_empty() {
24 println!("No Enpose devices found on the local network.");
25 return Ok(());
26 }
27
28 println!("Found {} device(s):", devices.len());
29 for device in &devices {
30 let status = if device.compatible {
31 "compatible"
32 } else {
33 "INCOMPATIBLE (protocol version mismatch)"
34 };
35 println!(" - {} (serial {}): {}", device.ip, device.serial, status);
36 }
37
38 // Pick the first compatible device to stream from.
39 let Some(device) = devices.iter().find(|d| d.compatible) else {
40 println!("No compatible device to stream poses from.");
41 return Ok(());
42 };
43
44 println!("\nStreaming poses from {} for {:?}...", device.ip, STREAM_DURATION);
45
46 // Threaded mode: a background thread receives and buffers poses, so none
47 // are missed regardless of how often we poll below.
48 let mut stream = PoseStream::from_device(device, true)?;
49
50 let start = Instant::now();
51 while start.elapsed() < STREAM_DURATION {
52 // Blocking receive: waits up to 3 s for a pose update, so no manual
53 // polling delay is needed.
54 for pose in stream.receive_pose_updates(true)? {
55 println!(
56 " t={:>10}us marker {:>3}: pos=({:+.4}, {:+.4}, {:+.4}) rmse={:.4} sensors={}",
57 pose.timestamp,
58 pose.marker_id,
59 pose.x,
60 pose.y,
61 pose.z,
62 pose.position_rmse,
63 pose.sensors,
64 );
65 }
66 }
67
68 // `stream` is dropped here, which disconnects from the device.
69 Ok(())
70}Sourcepub fn disconnect(&mut self)
pub fn disconnect(&mut self)
Disconnect the stream, closing the connection to the device.
Idempotent, and called automatically when the PoseStream is
dropped, so you only need to call it explicitly to disconnect early.