|
1 | 1 | import atexit |
2 | | -import time |
3 | 2 | import multiprocessing as mp |
| 3 | +import time |
4 | 4 | import uuid |
5 | 5 | from copy import deepcopy |
6 | 6 | from logging import getLogger |
|
35 | 35 | FRAME_DURATION = 1.0 / FPS |
36 | 36 |
|
37 | 37 |
|
38 | | -def gui_loop(model_bytes: bytes, close_event: Event, gui_uuid: str): |
| 38 | +def gui_loop(gui_uuid: str, close_event: Event): |
| 39 | + gui_client = _GuiClient(gui_uuid) |
| 40 | + model_bytes = gui_client.get_model_bytes() |
39 | 41 | with NamedTemporaryFile(mode="wb") as f: |
40 | 42 | f.write(model_bytes) |
41 | 43 | model = mujoco.MjModel.from_binary_path(f.name) |
42 | 44 | data = mujoco.MjData(model) |
43 | | - gui_client = _GuiClient(gui_uuid) |
44 | 45 | gui_client.set_model_and_data(model._address, data._address) |
45 | 46 | mujoco.mj_step(model, data) |
46 | 47 | with mujoco.viewer.launch_passive(model, data) as viewer: |
@@ -69,28 +70,29 @@ def __init__(self, mjmdl: str | PathLike): |
69 | 70 | logger.error(msg) |
70 | 71 | self.data = mj.MjData(self.model) |
71 | 72 | super().__init__(self.model._address, self.data._address) |
72 | | - self._gui_uuid: Optional[str] = None |
73 | 73 | self._mp_context = mp.get_context("spawn") |
| 74 | + self._gui_uuid: Optional[str] = None |
74 | 75 | self._gui_client: Optional[GuiClient] = None |
75 | | - self._gui_thread: Optional[Thread] = None |
| 76 | + self._gui_process: Optional[mp.Process] = None |
| 77 | + self._stop_event: Optional[mp.Event] = None |
| 78 | + |
| 79 | + def close_gui(self): |
| 80 | + if self._stop_event is not None: |
| 81 | + self._stop_event.set() |
| 82 | + if self._gui_process is not None: |
| 83 | + self._gui_process.join() |
| 84 | + self._stop_gui_server() |
76 | 85 |
|
77 | 86 | def open_gui(self): |
78 | 87 | if self._gui_uuid is None: |
79 | 88 | self._gui_uuid = "rcs_" + str(uuid.uuid4()) |
80 | 89 | self._start_gui_server(self._gui_uuid) |
81 | | - atexit.register(self._stop_gui_server) |
82 | 90 | if self._gui_client is None: |
83 | | - self._gui_client = _GuiClient(self._gui_uuid) |
84 | | - model_bytes = self._gui_client.get_model_bytes() |
85 | 91 | ctx = mp.get_context("spawn") |
86 | 92 | self._stop_event = ctx.Event() |
87 | 93 | self._gui_process = ctx.Process( |
88 | 94 | target=gui_loop, |
89 | | - args=(model_bytes, self._stop_event, self._gui_uuid), |
| 95 | + args=(self._gui_uuid, self._stop_event), |
90 | 96 | ) |
91 | 97 | self._gui_process.start() |
92 | | - |
93 | | - def __del__(self): |
94 | | - self._stop_event.set() |
95 | | - self._gui_process.join() |
96 | | - self._stop_gui_server() |
| 98 | + atexit.register(self.close_gui) |
0 commit comments