carrot/tools/sim/tests/test_sim_bridge.py
Vehicle Researcher 8eb8330d95 openpilot v0.9.9 release
date: 2025-03-08T09:09:29
master commit: ce355250be726f9bc8f0ac165a6cde41586a983d
2025-03-08 09:09:31 +00:00

93 lines
3.1 KiB
Python

import os
import subprocess
import time
import pytest
from multiprocessing import Queue
from cereal import messaging
from openpilot.common.basedir import BASEDIR
from openpilot.tools.sim.bridge.common import QueueMessageType
SIM_DIR = os.path.join(BASEDIR, "tools/sim")
class TestSimBridgeBase:
@classmethod
def setup_class(cls):
if cls is TestSimBridgeBase:
raise pytest.skip("Don't run this base class, run test_metadrive_bridge.py instead")
def setup_method(self):
self.processes = []
def test_driving(self):
# Startup manager and bridge.py. Check processes are running, then engage and verify.
p_manager = subprocess.Popen("./launch_openpilot.sh", cwd=SIM_DIR)
self.processes.append(p_manager)
sm = messaging.SubMaster(['selfdriveState', 'onroadEvents', 'managerState'])
q = Queue()
bridge = self.create_bridge()
p_bridge = bridge.run(q, retries=10)
self.processes.append(p_bridge)
max_time_per_step = 60
# Wait for bridge to startup
start_waiting = time.monotonic()
while not bridge.started.value and time.monotonic() < start_waiting + max_time_per_step:
time.sleep(0.1)
assert p_bridge.exitcode is None, f"Bridge process should be running, but exited with code {p_bridge.exitcode}"
start_time = time.monotonic()
no_car_events_issues_once = False
car_event_issues = []
not_running = []
while time.monotonic() < start_time + max_time_per_step:
sm.update()
not_running = [p.name for p in sm['managerState'].processes if not p.running and p.shouldBeRunning]
car_event_issues = [event.name for event in sm['onroadEvents'] if any([event.noEntry, event.softDisable, event.immediateDisable])]
if sm.all_alive() and len(car_event_issues) == 0 and len(not_running) == 0:
no_car_events_issues_once = True
break
assert no_car_events_issues_once, \
f"Failed because no messages received, or CarEvents '{car_event_issues}' or processes not running '{not_running}'"
start_time = time.monotonic()
min_counts_control_active = 100
control_active = 0
while time.monotonic() < start_time + max_time_per_step:
sm.update()
if sm.all_alive() and sm['selfdriveState'].active:
control_active += 1
if control_active == min_counts_control_active:
break
assert min_counts_control_active == control_active, f"Simulator did not engage a minimal of {min_counts_control_active} steps was {control_active}"
failure_states = []
while bridge.started.value:
continue
while not q.empty():
state = q.get()
if state.type == QueueMessageType.TERMINATION_INFO:
done_info = state.info
failure_states = [done_state for done_state in done_info if done_state != "timeout" and done_info[done_state]]
break
assert len(failure_states) == 0, f"Simulator fails to finish a loop. Failure states: {failure_states}"
def teardown_method(self):
print("Test shutting down. CommIssues are acceptable")
for p in reversed(self.processes):
p.terminate()
for p in reversed(self.processes):
p.kill()