Files
sunnypilot/openpilot/tools/wgpu/device.py
T
2026-07-25 02:41:08 -04:00

68 lines
1.9 KiB
Python

#!/usr/bin/env python3
import argparse
import signal
import subprocess
import time
from pathlib import Path
from openpilot.common.params import Params
MODEL_OUTPUTS = "modelV2,drivingModelData,cameraOdometry,modelDataV2SP"
ROOT = Path(__file__).resolve().parents[3]
BRIDGE = ROOT / "openpilot/cereal/messaging/bridge"
def stop_process(proc: subprocess.Popen) -> None:
proc.terminate()
try:
proc.wait(timeout=5)
except subprocess.TimeoutExpired:
proc.kill()
proc.wait()
def handle_sigterm(*_) -> None:
raise KeyboardInterrupt
def main() -> None:
parser = argparse.ArgumentParser(description="Route modeld traffic between this device and a wireless host.")
parser.add_argument("host", help="Laptop IP address reachable from this device")
args = parser.parse_args()
if not BRIDGE.is_file():
raise FileNotFoundError(f"build the cereal bridge first: {BRIDGE}")
params = Params()
if not params.get_bool("IsOffroad"):
raise RuntimeError("start the wgpu bridge while offroad")
procs: list[subprocess.Popen] = []
try:
params.put_bool("WgpuEnabled", True, block=True)
procs = [
subprocess.Popen([str(BRIDGE)]),
subprocess.Popen([str(BRIDGE), args.host, MODEL_OUTPUTS]),
]
print(f"wgpu enabled; forwarding camera/state to {args.host}")
print("keep this process running; Ctrl+C restores local modeld")
while all(proc.poll() is None for proc in procs):
time.sleep(0.25)
failed = next(proc for proc in procs if proc.poll() is not None)
raise RuntimeError(f"bridge exited with status {failed.returncode}")
finally:
params.put_bool("WgpuEnabled", False, block=True)
for proc in procs:
if proc.poll() is None:
stop_process(proc)
print("wgpu disabled; local modeld restored")
if __name__ == "__main__":
signal.signal(signal.SIGTERM, handle_sigterm)
try:
main()
except KeyboardInterrupt:
pass