Skip to content

Commit 2c4fa47

Browse files
committed
Use double buffered StateStorage reader in HulaWrapper
1 parent 5be745a commit 2c4fa47

File tree

4 files changed

+62
-27
lines changed

4 files changed

+62
-27
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hulk/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ license = "GPL-3.0-only"
66
homepage = "https://github.com/hulks/hulk"
77

88
[features]
9-
nao = ["alsa", "nao_camera", "v4l"]
9+
nao = ["alsa", "libc", "nao_camera", "v4l"]
1010

1111
[dependencies]
1212
alsa = { optional = true, workspace = true }
@@ -17,6 +17,7 @@ ctrlc = { workspace = true }
1717
cyclers = { workspace = true }
1818
fern = { workspace = true }
1919
i2cdev = { workspace = true }
20+
libc = { optional = true, workspace = true }
2021
log = { workspace = true }
2122
nalgebra = { workspace = true }
2223
nao_camera = { optional = true, workspace = true }

crates/hulk/src/nao/hula.rs

+45-22
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
use std::{
2-
io::{Read, Write},
3-
mem::size_of,
2+
io::{self, Write},
3+
mem::{size_of, MaybeUninit},
44
os::unix::net::UnixStream,
5-
ptr::read,
5+
ptr::null_mut,
66
slice::from_raw_parts,
77
};
88

9-
use color_eyre::Result;
9+
use color_eyre::{eyre::Context, Result};
10+
use libc::{fd_set, select, FD_SET, FD_ZERO};
1011
use nalgebra::{vector, Vector2, Vector3};
1112
use types::{self, ArmJoints, HeadJoints, Joints, LegJoints};
1213

13-
#[derive(Clone, Copy, Debug, Default)]
14+
use super::double_buffered_reader::DoubleBufferedReader;
15+
16+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
1417
#[repr(C)]
1518
pub struct RobotConfiguration {
1619
pub body_id: [u8; 20],
@@ -19,7 +22,7 @@ pub struct RobotConfiguration {
1922
pub head_version: u8,
2023
}
2124

22-
#[derive(Clone, Copy, Debug, Default)]
25+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
2326
#[repr(C)]
2427
pub struct Battery {
2528
pub charge: f32,
@@ -28,7 +31,7 @@ pub struct Battery {
2831
pub temperature: f32,
2932
}
3033

31-
#[derive(Clone, Copy, Debug, Default)]
34+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
3235
#[repr(C)]
3336
pub struct Vertex2 {
3437
x: f32,
@@ -41,7 +44,7 @@ impl From<Vertex2> for Vector2<f32> {
4144
}
4245
}
4346

44-
#[derive(Clone, Copy, Debug, Default)]
47+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
4548
#[repr(C)]
4649
pub struct Vertex3 {
4750
x: f32,
@@ -55,7 +58,7 @@ impl From<Vertex3> for Vector3<f32> {
5558
}
5659
}
5760

58-
#[derive(Clone, Copy, Debug, Default)]
61+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
5962
#[repr(C)]
6063
pub struct InertialMeasurementUnit {
6164
pub accelerometer: Vertex3,
@@ -73,7 +76,7 @@ impl From<InertialMeasurementUnit> for types::InertialMeasurementUnitData {
7376
}
7477
}
7578

76-
#[derive(Clone, Copy, Debug, Default)]
79+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
7780
#[repr(C)]
7881
pub struct ForceSensitiveResistors {
7982
left_foot_front_left: f32,
@@ -105,7 +108,7 @@ impl From<ForceSensitiveResistors> for types::ForceSensitiveResistors {
105108
}
106109
}
107110

108-
#[derive(Clone, Copy, Debug, Default)]
111+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
109112
#[repr(C)]
110113
pub struct TouchSensors {
111114
chest_button: bool,
@@ -145,7 +148,7 @@ impl From<TouchSensors> for types::TouchSensors {
145148
}
146149
}
147150

148-
#[derive(Clone, Copy, Debug, Default)]
151+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
149152
#[repr(C)]
150153
pub struct SonarSensors {
151154
pub left: f32,
@@ -161,7 +164,7 @@ impl From<SonarSensors> for types::SonarSensors {
161164
}
162165
}
163166

164-
#[derive(Clone, Copy, Debug, Default)]
167+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
165168
#[repr(C)]
166169
pub struct JointsArray {
167170
pub head_yaw: f32,
@@ -267,7 +270,7 @@ impl From<JointsArray> for Joints {
267270
}
268271
}
269272

270-
#[derive(Clone, Copy, Debug, Default)]
273+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
271274
#[repr(C)]
272275
pub struct StateStorage {
273276
/// Seconds since proxy start
@@ -285,7 +288,7 @@ pub struct StateStorage {
285288
pub status: JointsArray,
286289
}
287290

288-
#[derive(Clone, Copy, Debug, Default)]
291+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
289292
#[repr(C)]
290293
pub struct Color {
291294
pub red: f32,
@@ -303,7 +306,7 @@ impl From<types::Rgb> for Color {
303306
}
304307
}
305308

306-
#[derive(Clone, Copy, Debug, Default)]
309+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
307310
#[repr(C)]
308311
pub struct Eye {
309312
pub color_at_0: Color,
@@ -331,7 +334,7 @@ impl From<types::Eye> for Eye {
331334
}
332335
}
333336

334-
#[derive(Clone, Copy, Debug, Default)]
337+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
335338
#[repr(C)]
336339
pub struct Ear {
337340
pub intensity_at_0: f32,
@@ -363,7 +366,7 @@ impl From<types::Ear> for Ear {
363366
}
364367
}
365368

366-
#[derive(Clone, Copy, Debug, Default)]
369+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
367370
#[repr(C)]
368371
pub struct ControlStorage {
369372
pub left_eye: Eye,
@@ -377,10 +380,30 @@ pub struct ControlStorage {
377380
pub stiffness: JointsArray,
378381
}
379382

380-
pub fn read_from_hula(stream: &mut UnixStream) -> Result<StateStorage> {
381-
let mut read_buffer = [0; size_of::<StateStorage>()];
382-
stream.read_exact(&mut read_buffer)?;
383-
Ok(unsafe { read(read_buffer.as_ptr() as *const StateStorage) })
383+
pub fn read_from_hula(
384+
stream: &mut UnixStream,
385+
reader: &mut DoubleBufferedReader,
386+
) -> Result<StateStorage> {
387+
reader
388+
.read(stream, |file_descriptor| unsafe {
389+
let mut set = MaybeUninit::<fd_set>::uninit();
390+
FD_ZERO(set.as_mut_ptr());
391+
let mut set = set.assume_init();
392+
FD_SET(file_descriptor, &mut set);
393+
if select(
394+
file_descriptor + 1,
395+
&mut set,
396+
null_mut(),
397+
null_mut(),
398+
null_mut(),
399+
) < 0
400+
{
401+
return Err(io::Error::last_os_error());
402+
}
403+
Ok(())
404+
})
405+
.wrap_err("failed to read from stream")?;
406+
Ok(*reader.get_last())
384407
}
385408

386409
pub fn write_to_hula(stream: &mut UnixStream, control_storage: ControlStorage) -> Result<()> {

crates/hulk/src/nao/hula_wrapper.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,29 @@ use std::{
77
use color_eyre::{eyre::WrapErr, Result};
88
use types::{hardware::Ids, Joints, Leds, SensorData};
99

10-
use super::hula::{read_from_hula, write_to_hula, ControlStorage};
10+
use super::{
11+
double_buffered_reader::DoubleBufferedReader,
12+
hula::{read_from_hula, write_to_hula, ControlStorage},
13+
};
1114
use constants::HULA_SOCKET_PATH;
1215

1316
pub struct HulaWrapper {
1417
now: SystemTime,
1518
ids: Ids,
1619
stream: UnixStream,
20+
hula_reader: DoubleBufferedReader,
1721
}
1822

1923
impl HulaWrapper {
2024
pub fn new() -> Result<Self> {
2125
let mut stream =
2226
UnixStream::connect(HULA_SOCKET_PATH).wrap_err("failed to open HULA socket")?;
23-
let state_storage = read_from_hula(&mut stream).wrap_err("failed to read from HULA")?;
27+
stream
28+
.set_nonblocking(true)
29+
.wrap_err("failed to set HULA socket to non-blocking mode")?;
30+
let mut hula_reader = Default::default();
31+
let state_storage =
32+
read_from_hula(&mut stream, &mut hula_reader).wrap_err("failed to read from HULA")?;
2433
let ids = Ids {
2534
body_id: from_utf8(&state_storage.robot_configuration.body_id)
2635
.wrap_err("failed to convert body ID into UTF-8")?
@@ -33,6 +42,7 @@ impl HulaWrapper {
3342
now: UNIX_EPOCH,
3443
ids,
3544
stream,
45+
hula_reader,
3646
})
3747
}
3848

@@ -45,8 +55,8 @@ impl HulaWrapper {
4555
}
4656

4757
pub fn read_from_hula(&mut self) -> Result<SensorData> {
48-
let state_storage =
49-
read_from_hula(&mut self.stream).wrap_err("failed to read from HULA")?;
58+
let state_storage = read_from_hula(&mut self.stream, &mut self.hula_reader)
59+
.wrap_err("failed to read from HULA")?;
5060

5161
self.now = UNIX_EPOCH + Duration::from_secs_f32(state_storage.received_at);
5262

0 commit comments

Comments
 (0)