Skip to content

Commit be8f734

Browse files
authored
Solidify Scene{Description,State} typing (#2147)
* Expose Rust scene types to Python * sort imports * isort * isort * remove unused imports
1 parent e55e200 commit be8f734

13 files changed

Lines changed: 281 additions & 185 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hulk_mujoco/src/hardware_interface.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ use hardware::{
1818
TransformMessageInterface,
1919
};
2020
use hula_types::hardware::{Ids, Paths};
21-
use log::{error, warn};
21+
use log::{error, info, warn};
2222
use parking_lot::Mutex;
2323
use serde::Deserialize;
24-
use simulation_message::{ClientMessageKind, ConnectionInfo, ServerMessageKind, SimulationMessage};
24+
use simulation_message::{ClientMessageKind, ConnectionInfo, ServerMessageKind, SimulatorMessage};
2525
use tokio::sync::mpsc::{channel, Receiver, Sender};
2626
use tokio::time::sleep;
2727
use tokio_tungstenite::tungstenite::Message;
@@ -123,9 +123,7 @@ async fn worker(
123123
log::info!("connected to mujoco websocket at {address}");
124124
log::info!("sending ConnectionInfo");
125125
websocket
126-
.send(Message::Text(
127-
serde_json::to_string(&connection_info)?.into(),
128-
))
126+
.send(Message::binary(bincode::serialize(&connection_info)?))
129127
.await?;
130128
break websocket;
131129
};
@@ -144,7 +142,7 @@ async fn worker(
144142
},
145143
maybe_low_command_event = worker_channels.low_command_receiver.recv() => {
146144
match maybe_low_command_event {
147-
Some(low_command) => websocket.send(Message::Text(serde_json::to_string(&ClientMessageKind::LowCommand(low_command))?.into())).await?,
145+
Some(low_command) => websocket.send(Message::binary(bincode::serialize(&ClientMessageKind::LowCommand(low_command))?)).await?,
148146
None => break,
149147
};
150148
},
@@ -161,22 +159,22 @@ async fn handle_message(
161159
worker_channels: &WorkerChannels,
162160
) -> Result<()> {
163161
let message = match message {
164-
Message::Text(string) => serde_json::from_str(&string)?,
162+
Message::Binary(data) => bincode::deserialize(&data)?,
165163
Message::Close(maybe_frame) => {
166164
warn!("server closed connections: {maybe_frame:#?}");
167165
return Ok(());
168166
}
169167
_ => return Ok(()),
170168
};
171169
match message {
172-
SimulationMessage {
170+
SimulatorMessage {
173171
payload: ServerMessageKind::LowState(low_state),
174172
time,
175173
} => {
176174
*hardware_interface_time.lock() = time;
177175
worker_channels.low_state_sender.send(low_state).await?
178176
}
179-
SimulationMessage {
177+
SimulatorMessage {
180178
payload: ServerMessageKind::FallDownState(fall_down_state),
181179
time,
182180
} => {
@@ -186,7 +184,7 @@ async fn handle_message(
186184
.send(fall_down_state)
187185
.await?
188186
}
189-
SimulationMessage {
187+
SimulatorMessage {
190188
payload: ServerMessageKind::ButtonEventMsg(button_event_msg),
191189
time,
192190
} => {
@@ -196,7 +194,7 @@ async fn handle_message(
196194
.send(button_event_msg)
197195
.await?
198196
}
199-
SimulationMessage {
197+
SimulatorMessage {
200198
payload: ServerMessageKind::RemoteControllerState(remote_controller_state),
201199
time,
202200
} => {
@@ -206,7 +204,7 @@ async fn handle_message(
206204
.send(remote_controller_state)
207205
.await?
208206
}
209-
SimulationMessage {
207+
SimulatorMessage {
210208
payload: ServerMessageKind::TransformMessage(transform_stamped),
211209
time,
212210
} => {
@@ -216,7 +214,7 @@ async fn handle_message(
216214
.send(transform_stamped)
217215
.await?
218216
}
219-
SimulationMessage {
217+
SimulatorMessage {
220218
payload: ServerMessageKind::RGBDSensors(rgbd_sensors),
221219
time,
222220
} => {
@@ -226,6 +224,9 @@ async fn handle_message(
226224
.send(*rgbd_sensors)
227225
.await?
228226
}
227+
_ => {
228+
info!("Received unexpected simulator data")
229+
}
229230
};
230231

231232
Ok(())

crates/simulation_message/src/lib.rs

Lines changed: 136 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
use std::{
2+
collections::BTreeMap,
23
ops::Range,
34
time::{Duration, SystemTime},
45
};
56

67
use booster::{
78
ButtonEventMsg, FallDownState, LowCommand, LowState, RemoteControllerState, TransformMessage,
89
};
9-
use pyo3::pyclass;
10+
use pyo3::{pyclass, pymethods};
1011
use serde::{Deserialize, Serialize};
1112
use zed::RGBDSensors;
1213

1314
#[derive(Clone, Debug, Serialize, Deserialize)]
14-
pub struct SimulationMessage<T> {
15+
pub struct SimulatorMessage<T> {
1516
pub time: SystemTime,
1617
pub payload: T,
1718
}
@@ -24,6 +25,8 @@ pub enum ServerMessageKind {
2425
RemoteControllerState(RemoteControllerState),
2526
TransformMessage(TransformMessage),
2627
RGBDSensors(Box<RGBDSensors>),
28+
SceneUpdate(SceneUpdate),
29+
SceneDescription(SceneDescription),
2730
}
2831

2932
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -44,6 +47,137 @@ pub enum TaskName {
4447
RequestSceneDescription,
4548
}
4649

50+
#[pyclass(frozen)]
51+
#[derive(Clone, Debug, Serialize, Deserialize)]
52+
pub struct SceneDescription {
53+
pub meshes: BTreeMap<String, SceneMesh>,
54+
pub lights: Vec<Light>,
55+
pub bodies: BTreeMap<String, Body>,
56+
}
57+
58+
#[pymethods]
59+
impl SceneDescription {
60+
#[new]
61+
pub fn new(
62+
meshes: BTreeMap<String, SceneMesh>,
63+
lights: Vec<Light>,
64+
bodies: BTreeMap<String, Body>,
65+
) -> Self {
66+
Self {
67+
meshes,
68+
lights,
69+
bodies,
70+
}
71+
}
72+
}
73+
74+
#[pyclass(frozen)]
75+
#[derive(Clone, Debug, Serialize, Deserialize)]
76+
pub struct SceneMesh {
77+
pub vertices: Vec<[f32; 3]>,
78+
pub faces: Vec<[u32; 3]>,
79+
}
80+
81+
#[pymethods]
82+
impl SceneMesh {
83+
#[new]
84+
pub fn new(vertices: Vec<[f32; 3]>, faces: Vec<[u32; 3]>) -> Self {
85+
Self { vertices, faces }
86+
}
87+
}
88+
89+
#[pyclass(frozen)]
90+
#[derive(Clone, Debug, Serialize, Deserialize)]
91+
pub struct Light {
92+
pub name: Option<String>,
93+
pub pos: [f32; 3],
94+
pub dir: [f32; 3],
95+
}
96+
97+
#[pymethods]
98+
impl Light {
99+
#[new]
100+
pub fn new(name: Option<String>, pos: [f32; 3], dir: [f32; 3]) -> Self {
101+
Self { name, pos, dir }
102+
}
103+
}
104+
105+
#[pyclass(frozen)]
106+
#[derive(Clone, Debug, Serialize, Deserialize)]
107+
pub struct Body {
108+
pub id: i64,
109+
pub parent: Option<String>,
110+
pub geoms: Vec<Geom>,
111+
}
112+
113+
#[pymethods]
114+
impl Body {
115+
#[new]
116+
pub fn new(id: i64, parent: Option<String>, geoms: Vec<Geom>) -> Self {
117+
Self { id, parent, geoms }
118+
}
119+
}
120+
121+
#[pyclass(frozen)]
122+
#[derive(Clone, Debug, Serialize, Deserialize)]
123+
pub struct Geom {
124+
pub name: Option<String>,
125+
pub mesh: Option<String>,
126+
pub rgba: [f32; 4],
127+
pub pos: [f32; 3],
128+
pub quat: [f32; 4],
129+
}
130+
131+
#[pymethods]
132+
impl Geom {
133+
#[new]
134+
pub fn new(
135+
name: Option<String>,
136+
mesh: Option<String>,
137+
rgba: [f32; 4],
138+
pos: [f32; 3],
139+
quat: [f32; 4],
140+
) -> Self {
141+
Self {
142+
name,
143+
mesh,
144+
rgba,
145+
pos,
146+
quat,
147+
}
148+
}
149+
}
150+
151+
#[pyclass(frozen)]
152+
#[derive(Clone, Debug, Serialize, Deserialize)]
153+
pub struct SceneUpdate {
154+
pub time: f32,
155+
pub bodies: BTreeMap<String, BodyUpdate>,
156+
}
157+
158+
#[pymethods]
159+
impl SceneUpdate {
160+
#[new]
161+
pub fn new(time: f32, bodies: BTreeMap<String, BodyUpdate>) -> Self {
162+
Self { time, bodies }
163+
}
164+
}
165+
166+
#[pyclass(frozen)]
167+
#[derive(Clone, Debug, Serialize, Deserialize)]
168+
pub struct BodyUpdate {
169+
pub pos: [f32; 3],
170+
pub quat: [f32; 4],
171+
}
172+
173+
#[pymethods]
174+
impl BodyUpdate {
175+
#[new]
176+
pub fn new(pos: [f32; 3], quat: [f32; 4]) -> Self {
177+
Self { pos, quat }
178+
}
179+
}
180+
47181
#[derive(Debug, Serialize, Deserialize)]
48182
pub struct ConnectionInfo {
49183
pub schedule: Vec<TaskSchedule>,

tools/mujoco-simulator/mujoco-rust-server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ name = "mujoco_rust_server"
1010
crate-type = ["cdylib"]
1111

1212
[dependencies]
13+
bincode = { workspace = true }
1314
booster = { workspace = true }
1415
color-eyre = { workspace = true }
1516
futures-util = { workspace = true }

tools/mujoco-simulator/mujoco-rust-server/mujoco_rust_server/mujoco_rust_server.pyi

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ class PySimulationTask:
1212
async def respond(
1313
self,
1414
time: float,
15-
response: booster_types.LowState | zed_types.RGBDSensors | bytes | str | None,
15+
response: booster_types.LowState
16+
| zed_types.RGBDSensors
17+
| bytes
18+
| str
19+
| None,
1620
) -> None: ...
1721
async def receive(self) -> booster_types.LowCommand: ...
1822

@@ -26,8 +30,49 @@ class TaskName(Enum):
2630
Reset = auto()
2731
Invalid = auto()
2832

33+
class Body:
34+
id: int
35+
parent: str | None
36+
geoms: list[Geom]
37+
38+
class BodyUpdate:
39+
pos: list[float]
40+
quat: list[float]
41+
42+
class Geom:
43+
name: str
44+
mesh: str | None
45+
rgba: list[float]
46+
pos: list[float]
47+
quat: list[float]
48+
49+
class Light:
50+
name: str | None
51+
pos: list[float]
52+
dir: list[float]
53+
54+
class SceneDescription:
55+
meshes: dict[str, SceneMesh]
56+
lights: list[Light]
57+
bodies: dict[str, Body]
58+
59+
class SceneMesh:
60+
vertices: list[list[float]]
61+
faces: list[list[int]]
62+
63+
class SceneUpdate:
64+
time: float
65+
bodies: dict[str, BodyUpdate]
66+
2967
__all__ = [
68+
"Body",
69+
"BodyUpdate",
70+
"Geom",
71+
"Light",
3072
"PySimulationTask",
73+
"SceneDescription",
74+
"SceneMesh",
75+
"SceneUpdate",
3176
"SimulationServer",
3277
"TaskName",
3378
"booster_types",

0 commit comments

Comments
 (0)