Skip to content

Commit 0411214

Browse files
committed
Make Pico signal diagnostics interruptible
1 parent 991c49a commit 0411214

1 file changed

Lines changed: 39 additions & 3 deletions

File tree

scripts/run/check_pico_signal.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
from collections import Counter
66
import logging
7+
import os
8+
import signal
79
import time
10+
import threading
811
from typing import Any
912

1013
import hydra
@@ -164,6 +167,31 @@ def _build_provider(cfg: DictConfig, video_enabled: bool) -> Pico4InputProvider:
164167
)
165168

166169

170+
def _install_signal_handlers(stop_event: threading.Event) -> None:
171+
def _handle_signal(signum: int, _frame: Any) -> None:
172+
if stop_event.is_set():
173+
os._exit(130)
174+
logger.info("Received signal %s -- shutting down", signum)
175+
stop_event.set()
176+
177+
signal.signal(signal.SIGINT, _handle_signal)
178+
signal.signal(signal.SIGTERM, _handle_signal)
179+
180+
181+
def _start_video_runtime_async(video_runtime: PicoVideoRuntime) -> threading.Event:
182+
done = threading.Event()
183+
184+
def _run() -> None:
185+
try:
186+
video_runtime.start()
187+
finally:
188+
done.set()
189+
190+
thread = threading.Thread(target=_run, name="pico_video_start", daemon=True)
191+
thread.start()
192+
return done
193+
194+
167195
@hydra.main(version_base=None, config_path="../../teleopit/configs", config_name="pico4_sim2real")
168196
def main(cfg: DictConfig) -> None:
169197
logging.basicConfig(level=logging.INFO, format="%(levelname)s:%(name)s:%(message)s")
@@ -195,6 +223,8 @@ def main(cfg: DictConfig) -> None:
195223
video_cfg.source,
196224
)
197225

226+
stop_event = threading.Event()
227+
_install_signal_handlers(stop_event)
198228
provider = _build_provider(cfg, video_cfg.enabled)
199229
video_runtime = PicoVideoRuntime(provider=provider, config=video_cfg, mode="sim2real")
200230
total = 0
@@ -206,10 +236,13 @@ def main(cfg: DictConfig) -> None:
206236
window_start_s = time.monotonic()
207237
start_s = window_start_s
208238
sleep_s = 1.0 / max(poll_hz, 1.0)
239+
video_start_done: threading.Event | None = None
209240

210241
try:
211-
video_runtime.start()
212-
while True:
242+
if video_cfg.enabled:
243+
logger.info("Starting Pico video backend asynchronously")
244+
video_start_done = _start_video_runtime_async(video_runtime)
245+
while not stop_event.is_set():
213246
now = time.monotonic()
214247
if duration_s > 0.0 and now - start_s >= duration_s:
215248
break
@@ -252,7 +285,10 @@ def main(cfg: DictConfig) -> None:
252285
invalid_reasons.clear()
253286
window_start_s = now
254287

255-
time.sleep(sleep_s)
288+
if video_start_done is not None and not video_start_done.is_set() and now - start_s >= 5.0:
289+
logger.info("Waiting for Pico video backend to become ready in the background")
290+
video_start_done = None
291+
stop_event.wait(timeout=sleep_s)
256292
except KeyboardInterrupt:
257293
logger.info("KeyboardInterrupt -- stopping Pico signal diagnostic")
258294
finally:

0 commit comments

Comments
 (0)