Skip to content

Commit 65dfbb6

Browse files
authored
feat(sim): Interactive sim viewer in separate process
cf. PR #137 BREAKING CHANGE: removed `on_screen` sim camera
2 parents ae373b3 + f30e924 commit 65dfbb6

23 files changed

Lines changed: 362 additions & 53 deletions

CMakeLists.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,29 @@ FetchContent_Declare(pybind11
6767
GIT_PROGRESS TRUE
6868
EXCLUDE_FROM_ALL
6969
)
70+
set(MuJoCo_UI_URL https://raw.githubusercontent.com/google-deepmind/mujoco/${MuJoCo_VERSION}/simulate/)
71+
set(MuJoCo_UI_FILES platform_ui_adapter.cc platform_ui_adapter.h glfw_adapter.cc glfw_adapter.h glfw_adapter.cc glfw_corevideo.h glfw_corevideo.mm glfw_dispatch.cc glfw_dispatch.h)
72+
# Set the destination directory for the downloaded files
73+
set(MuJoCo_UI_DIR "${CMAKE_BINARY_DIR}/mujoco_ui")
74+
75+
# Create the directory if it doesn't exist
76+
file(MAKE_DIRECTORY ${MuJoCo_UI_DIR})
77+
78+
# Loop through each file and download it only if it doesn't already exist
79+
foreach(file ${MuJoCo_UI_FILES})
80+
set(output_file "${MuJoCo_UI_DIR}/${file}")
81+
if (NOT EXISTS ${output_file})
82+
message(STATUS "Downloading ${file}...")
83+
file(DOWNLOAD ${MuJoCo_UI_URL}${file} ${output_file})
84+
else()
85+
message(STATUS "File ${file} already exists, skipping download.")
86+
endif()
87+
endforeach()
88+
89+
# Add the include directories or link the files as needed
90+
add_library(mujoco_ui_lib ${MuJoCo_UI_DIR}/glfw_adapter.cc ${MuJoCo_UI_DIR}/platform_ui_adapter.cc ${MuJoCo_UI_DIR}/glfw_dispatch.cc)
91+
target_link_libraries(mujoco_ui_lib MuJoCo::MuJoCo glfw)
92+
target_include_directories(mujoco_ui_lib INTERFACE ${MuJoCo_UI_DIR})
7093

7194
FetchContent_MakeAvailable(libfranka rl pybind11)
7295

python/examples/env_cartesian_control.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ def main():
5353
camera_set_cfg=default_mujoco_cameraset_cfg(),
5454
max_relative_movement=0.5,
5555
)
56+
env_rel.get_wrapper_attr("sim").open_gui()
5657

5758
env_rel.reset()
5859
print(env_rel.unwrapped.robot.get_cartesian_position())

python/examples/env_joint_control.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def main():
5656
camera_set_cfg=default_mujoco_cameraset_cfg(),
5757
max_relative_movement=np.deg2rad(5),
5858
)
59+
env_rel.get_wrapper_attr("sim").open_gui()
5960

6061
for _ in range(10):
6162
obs, info = env_rel.reset()

python/examples/fr3.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,16 @@ def main():
5959
# add camera to have a rendering gui
6060
cameras = {
6161
"default_free": SimCameraConfig(
62-
identifier="", type=int(CameraType.default_free), on_screen_render=True
62+
identifier="", type=int(CameraType.default_free)
6363
),
6464
"wrist": SimCameraConfig(
65-
identifier="eye-in-hand_0", type=int(CameraType.fixed), on_screen_render=False
65+
identifier="eye-in-hand_0", type=int(CameraType.fixed)
6666
),
6767
# TODO: odd behavior when not both cameras are used: only last image is shown
6868
}
6969
cam_cfg = SimCameraSetConfig(cameras=cameras, resolution_width=1280, resolution_height=720, frame_rate=20)
7070
camera_set = SimCameraSet(simulation, cam_cfg)
71+
simulation.open_gui()
7172

7273
else:
7374
robot = rcsss.hw.FR3(ROBOT_IP, str(rcsss.scenes["lab"].parent / "fr3.urdf"))

python/rcsss/_core/sim.pyi

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ __all__ = [
2525
"default_free",
2626
"fixed",
2727
"free",
28+
"open_gui_window",
2829
"tracking",
2930
]
3031
M = typing.TypeVar("M", bound=int)
@@ -133,14 +134,15 @@ class FrankaHand(rcsss._core.common.Gripper):
133134

134135
class Sim:
135136
def __init__(self, mjmdl: int, mjdata: int) -> None: ...
137+
def _start_gui_server(self, id: str) -> None: ...
138+
def _stop_gui_server(self) -> None: ...
136139
def is_converged(self) -> bool: ...
137140
def reset(self) -> None: ...
138141
def step(self, k: int) -> None: ...
139142
def step_until_convergence(self) -> None: ...
140143

141144
class SimCameraConfig:
142145
identifier: str
143-
on_screen_render: bool
144146
type: CameraType
145147
def __init__(self) -> None: ...
146148

@@ -159,6 +161,8 @@ class SimCameraSetConfig:
159161
resolution_width: int
160162
def __init__(self) -> None: ...
161163

164+
def open_gui_window(uuid: str) -> None: ...
165+
162166
default_free: CameraType # value = <CameraType.default_free: 3>
163167
fixed: CameraType # value = <CameraType.fixed: 2>
164168
free: CameraType # value = <CameraType.free: 0>

python/rcsss/camera/sim.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
class SimCameraConfig(BaseCameraConfig):
2222
type: int # CamBaseCameraConfigeraType
23-
on_screen_render: bool
2423

2524

2625
class SimCameraSetConfig(BaseCameraSetConfig):
@@ -50,7 +49,6 @@ def get_type(t):
5049
for name, camera_cfg in cfg.cameras.items():
5150
cpp_camera_cfg = _SimCameraConfig()
5251
cpp_camera_cfg.type = get_type(camera_cfg.type)
53-
cpp_camera_cfg.on_screen_render = camera_cfg.on_screen_render
5452
cpp_camera_cfg.identifier = camera_cfg.identifier
5553
cameras[name] = cpp_camera_cfg
5654

python/rcsss/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def create_sample_config_yaml(path: str):
4545
camera_config=camera_cfg,
4646
camera_type="realsense",
4747
)
48-
cameras_sim = {"human_readable_name": SimCameraConfig(identifier="mjcf_name", type=0, on_screen_render=False)}
48+
cameras_sim = {"human_readable_name": SimCameraConfig(identifier="mjcf_name", type=0)}
4949
sim = SimConfig(camera=SimCameraSetConfig(cameras=cameras_sim))
5050
cfg = Config(hw=hw, sim=sim)
5151
yml = to_yaml_str(cfg)

python/rcsss/control/liveplot.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from itertools import product
33
from socket import AF_INET, SOCK_DGRAM, socket
44
from struct import unpack
5+
from typing import Optional
56

67
import matplotlib.pyplot as plt
78
import numpy as np
@@ -18,7 +19,7 @@
1819
titles = [["x", "rx"], ["y", "ry"], ["z", "rz"]]
1920
colors = [["r", "r"], ["b", "b"], ["g", "g"]]
2021
buffers: list[list[deque]] = [[deque(maxlen=buffsize) for j in range(2)] for i in range(3)]
21-
plots: list[list[plt.Figure]] = [[None for j in range(2)] for i in range(3)]
22+
plots: list[list[Optional[plt.Figure]]] = [[None for j in range(2)] for i in range(3)]
2223

2324
fig, axs = plt.subplots(3, 2)
2425
for i, j in product(range(3), range(2)):
@@ -56,8 +57,9 @@
5657

5758
for i, j in product(range(3), range(2)):
5859
buffer = buffers[i][j]
59-
plots[i][j].set_xdata(np.arange(len(buffer)))
60-
plots[i][j].set_ydata(buffer)
60+
# mypy fails to coerce type after assert so we just ignore
61+
plots[i][j].set_xdata(np.arange(len(buffer))) # type: ignore
62+
plots[i][j].set_ydata(buffer) # type: ignore
6163
axs[i][j].relim()
6264
axs[i][j].autoscale_view()
6365
axs[i][j].set_title(titles[i][j] + ": {:.2f}".format(buffer[-1]))

python/rcsss/control/vive.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,8 @@ def sim():
251251
env_sim = FR3Sim(FR3Env(robot, ControlMode.JOINTS), simulation)
252252

253253
cameras = {
254-
"wrist": SimCameraConfig(identifier="eye-in-hand_0", type=int(CameraType.fixed), on_screen_render=False),
255-
"default_free": SimCameraConfig(identifier="", type=int(CameraType.default_free), on_screen_render=True),
254+
"wrist": SimCameraConfig(identifier="eye-in-hand_0", type=int(CameraType.fixed)),
255+
"default_free": SimCameraConfig(identifier="", type=int(CameraType.default_free)),
256256
}
257257
cam_cfg = SimCameraSetConfig(cameras=cameras, resolution_width=640, resolution_height=480, frame_rate=10)
258258
camera_set = SimCameraSet(simulation, cam_cfg)

python/rcsss/envs/factories.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ def default_fr3_sim_gripper_cfg():
114114
def default_mujoco_cameraset_cfg():
115115

116116
cameras = {
117-
"wrist": SimCameraConfig(identifier="eye-in-hand_0", type=int(CameraType.fixed), on_screen_render=False),
118-
"default_free": SimCameraConfig(identifier="", type=int(CameraType.default_free), on_screen_render=True),
117+
"wrist": SimCameraConfig(identifier="eye-in-hand_0", type=int(CameraType.fixed)),
118+
"default_free": SimCameraConfig(identifier="", type=int(CameraType.default_free)),
119119
}
120120
return SimCameraSetConfig(cameras=cameras, resolution_width=1280, resolution_height=720, frame_rate=10)
121121

0 commit comments

Comments
 (0)