diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index 08d3abaca9..aaa6be829a 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -9,3 +9,5 @@ RUN pip install ipython jupyter jupyterlab
RUN cd $HOME && \
curl -O https://raw.githubusercontent.com/commaai/agnos-builder/master/userspace/home/.tmux.conf && \
curl -O https://github.com/commaai/agnos-builder/blob/master/userspace/home/.vimrc
+
+ENV CARLA_HOST="host.docker.internal"
\ No newline at end of file
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 7224f251a7..ef6534c1ae 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -18,7 +18,8 @@
"--volume=${localEnv:HOME}/.comma:/root/.comma",
"--volume=/tmp/comma_download_cache:/tmp/comma_download_cache",
"--volume=/tmp/devcontainer_scons_cache:/tmp/scons_cache",
- "--shm-size=1G"
+ "--shm-size=1G",
+ "--add-host=host.docker.internal:host-gateway" // required to use host.docker.internal on linux
],
"customizations": {
"vscode": {
diff --git a/.github/workflows/selfdrive_tests.yaml b/.github/workflows/selfdrive_tests.yaml
index 854faf4545..92b84f0af9 100644
--- a/.github/workflows/selfdrive_tests.yaml
+++ b/.github/workflows/selfdrive_tests.yaml
@@ -70,7 +70,10 @@ jobs:
build:
strategy:
matrix:
- arch: ${{ fromJson( (github.repository == 'commaai/openpilot') && '["x86_64", "aarch64"]' || '["x86_64"]' ) }}
+ arch: ${{ fromJson(
+ ((github.repository == 'commaai/openpilot') &&
+ ((github.event_name != 'pull_request') ||
+ (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && '["x86_64", "aarch64"]' || '["x86_64"]' ) }}
runs-on: ${{ (matrix.arch == 'aarch64') && 'buildjet-2vcpu-ubuntu-2204-arm' || 'ubuntu-20.04' }}
steps:
- uses: actions/checkout@v3
@@ -277,7 +280,9 @@ jobs:
process_replay:
name: process replay
- runs-on: ${{ ((github.event.pull_request.head.repo.full_name == 'commaai/openpilot') || (github.repository == 'commaai/openpilot')) && 'buildjet-8vcpu-ubuntu-2004' || 'ubuntu-20.04' }}
+ runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
+ ((github.event_name != 'pull_request') ||
+ (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'buildjet-8vcpu-ubuntu-2004' || 'ubuntu-20.04' }}
steps:
- uses: actions/checkout@v3
with:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index e612dfa74a..46ecbeb8ce 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -10,6 +10,7 @@ repos:
- id: check-ast
exclude: '^(third_party)/'
- id: check-json
+ exclude: '.devcontainer/devcontainer.json' # this supports JSON with comments
- id: check-toml
- id: check-xml
- id: check-yaml
diff --git a/selfdrive/test/helpers.py b/selfdrive/test/helpers.py
index eb07432c40..a6190b20b5 100644
--- a/selfdrive/test/helpers.py
+++ b/selfdrive/test/helpers.py
@@ -69,3 +69,7 @@ def with_processes(processes, init_time=0, ignore_stopped=None):
return wrap
return wrapper
+
+
+def noop(*args, **kwargs):
+ pass
\ No newline at end of file
diff --git a/selfdrive/thermald/tests/test_power_monitoring.py b/selfdrive/thermald/tests/test_power_monitoring.py
index c3a890f068..f8d43737cd 100755
--- a/selfdrive/thermald/tests/test_power_monitoring.py
+++ b/selfdrive/thermald/tests/test_power_monitoring.py
@@ -3,6 +3,7 @@ import unittest
from unittest.mock import patch
from openpilot.common.params import Params
+from openpilot.selfdrive.test.helpers import noop
from openpilot.selfdrive.thermald.power_monitoring import PowerMonitoring, CAR_BATTERY_CAPACITY_uWh, \
CAR_CHARGING_RATE_W, VBATT_PAUSE_CHARGING, DELAY_SHUTDOWN_TIME_S
@@ -25,6 +26,7 @@ def pm_patch(name, value, constant=False):
@patch("time.monotonic", new=mock_time_monotonic)
+@patch("openpilot.selfdrive.thermald.power_monitoring.put_nonblocking", new=noop) # TODO: Remove this once nonblocking params are safer
class TestPowerMonitoring(unittest.TestCase):
def setUp(self):
self.params = Params()
diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts
index 57d9f91fec..0ffef3bb7b 100644
--- a/selfdrive/ui/translations/main_zh-CHT.ts
+++ b/selfdrive/ui/translations/main_zh-CHT.ts
@@ -171,15 +171,15 @@
Reset Calibration
- 重置校準
+ 重設校準
RESET
- 重置
+ 重設
Are you sure you want to reset calibration?
- 您確定要重置校準嗎?
+ 您確定要重設校準嗎?
Review Training Guide
@@ -227,7 +227,7 @@
openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required.
- openpilot 需要將設備固定在左右偏差 4° 以內,朝上偏差 5° 以内或朝下偏差 8° 以内。鏡頭在後台會持續自動校準,很少有需要重置的情况。
+ openpilot 需要將設備固定在左右偏差 4° 以內,朝上偏差 5° 以內或朝下偏差 8° 以內。鏡頭在後台會持續自動校準,很少有需要重設的情況。
Your device is pointed %1° %2 and %3° %4.
@@ -290,7 +290,7 @@
PAST WEEK
- 上周
+ 上週
KM
@@ -369,7 +369,7 @@
MapWindow
Map Loading
- 地圖加載中
+ 地圖載入中
Waiting for GPS
@@ -452,11 +452,11 @@
openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai.
- openpilot 無法識別您的車輛。您的車輛可能未被支援,或是其電控單元 (ECU) 未被識別。請提交一個 Pull Request 為您的車輛添加正確的固件版本。需要幫助嗎?請加入 discord.comma.ai 。
+ openpilot 無法識別您的車輛。您的車輛可能未被支援,或是其電控單元 (ECU) 未被識別。請提交一個 Pull Request 為您的車輛添加正確的韌體版本。需要幫助嗎?請加入 discord.comma.ai 。
openpilot was unable to identify your car. Check integrity of cables and ensure all connections are secure, particularly that the comma power is fully inserted in the OBD-II port of the vehicle. Need help? Join discord.comma.ai.
- openpilot 無法識別您的車輛。請檢查線路是否正確的安裝並確保所有的連接都牢固,特別是確保 comma power 完全插入車輛的 OBD-II 接口。需要幫助嗎?請加入 discord.comma.ai 。
+ openpilot 無法識別您的車輛。請檢查線路是否正確的安裝並確保所有的連接都牢固,特別是確保 comma power 完全插入車輛的 OBD-II 介面。需要幫助嗎?請加入 discord.comma.ai 。
openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield.
@@ -498,7 +498,7 @@
Bookmark connect.comma.ai to your home screen to use it like an app
- 將 connect.comma.ai 加入您的主屏幕,以便像手機 App 一樣使用它
+ 將 connect.comma.ai 加入您的主螢幕,以便像手機 App 一樣使用它
@@ -528,7 +528,7 @@
Remote access
- 遠程訪問
+ 遠端存取
24/7 LTE connectivity
@@ -611,15 +611,15 @@
Reset
Reset failed. Reboot to try again.
- 重置失敗。請重新啟動後再試。
+ 重設失敗。請重新啟動後再試。
Are you sure you want to reset your device?
- 您確定要重置你的設備嗎?
+ 您確定要重設你的設備嗎?
System Reset
- 系統重置
+ 系統重設
Cancel
@@ -644,7 +644,7 @@
Resetting device...
This may take up to a minute.
- 設備重置中…
+ 設備重設中…
這可能需要一分鐘的時間。
@@ -699,7 +699,7 @@ This may take up to a minute.
Connect to Wi-Fi
- 連接到無線網絡
+ 連接到無線網路
Back
@@ -719,7 +719,7 @@ This may take up to a minute.
for Custom Software
- 定制的軟體
+ 訂製的軟體
Downloading...
@@ -829,27 +829,27 @@ This may take up to a minute.
Wi-Fi
-
+ Wi-Fi
ETH
-
+ ETH
2G
-
+ 2G
3G
-
+ 3G
LTE
-
+ LTE
5G
-
+ 5G
@@ -931,11 +931,11 @@ This may take up to a minute.
SshControl
SSH Keys
- SSH 密鑰
+ SSH 金鑰
Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username.
- 警告:這將授權給 GitHub 帳號中所有公鑰 SSH 訪問權限。切勿輸入非您自己的 GitHub 用戶名。comma 員工「永遠不會」要求您添加他們的 GitHub 用戶名。
+ 警告:這將授權給 GitHub 帳號中所有公鑰 SSH 訪問權限。切勿輸入非您自己的 GitHub 使用者名稱。comma 員工「永遠不會」要求您添加他們的 GitHub 使用者名稱。
ADD
@@ -943,7 +943,7 @@ This may take up to a minute.
Enter your GitHub username
- 請輸入您 GitHub 的用戶名
+ 請輸入您 GitHub 的使用者名稱
LOADING
@@ -955,7 +955,7 @@ This may take up to a minute.
Username '%1' has no keys on GitHub
- GitHub 用戶 '%1' 沒有設定任何密鑰
+ GitHub 用戶 '%1' 沒有設定任何金鑰
Request timed out
@@ -1024,7 +1024,7 @@ This may take up to a minute.
Upload data from the driver facing camera and help improve the driver monitoring algorithm.
- 上傳駕駛監控的錄像來協助我們提升駕駛監控的準確率。
+ 上傳駕駛監控的錄影來協助我們提升駕駛監控的準確率。
Disengage on Accelerator Pedal
@@ -1080,7 +1080,7 @@ This may take up to a minute.
WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB).
- 警告:此車輛的 openpilot 縱向控制功能目前處於 Alpha 版本,使用此功能將會停用自動緊急制動(AEB)功能。
+ 警告:此車輛的 openpilot 縱向控制功能目前處於 Alpha 版本,使用此功能將會停用自動緊急煞車(AEB)功能。
On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha.
@@ -1124,11 +1124,11 @@ This may take up to a minute.
When navigation has a destination, openpilot will input the map information into the model. This provides useful context for the model and allows openpilot to keep left or right appropriately at forks/exits. Lane change behavior is unchanged and still activated by the driver. This is an alpha quality feature; mistakes should be expected, particularly around exits and forks. These mistakes can include unintended laneline crossings, late exit taking, driving towards dividing barriers in the gore areas, etc.
- 当导航有目的地时,openpilot 将把地图信息输入模型中。这为模型提供了有用的背景信息,使 openpilot 能够在叉路/出口时适当地保持左侧或右侧行驶。车道变换行为保持不变,仍由驾驶员激活。这是一个 Alpha 版的功能;可能会出现错误,特别是在出口和分叉处。这些错误可能包括意外的车道越界、晚出口、朝着分隔栏驶向分隔带区域等。
+ 當導航有目的地時,openpilot 將把地圖資訊輸入模型中。這為模型提供了有用的背景資訊,使 openpilot 能夠在叉路/出口時適當地保持左側或右側行駛。車道變換行為保持不變,仍由駕駛員啟用。這是一個 Alpha 版的功能;可能會出現錯誤,特別是在出口和分叉處。這些錯誤可能包括意外的車道越界、晚出口、朝著分隔欄駛向分隔帶區域等。
The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner. When a navigation destination is set and the driving model is using it as input, the driving path on the map will turn green.
- 行駛畫面將在低速時切換至道路朝向的廣角鏡頭,以更好地顯示一些轉彎。實驗模式圖標也將顯示在右上角。當設定了導航目的地並且行駛模型正在將其作為輸入時,地圖上的行駛路徑將變為綠色。
+ 行駛畫面將在低速時切換至道路朝向的廣角鏡頭,以更好地顯示一些轉彎。實驗模式圖示也將顯示在右上角。當設定了導航目的地並且行駛模型正在將其作為輸入時,地圖上的行駛路徑將變為綠色。
@@ -1143,7 +1143,7 @@ This may take up to a minute.
Connect to Wi-Fi
- 連接到無線網絡
+ 連接到無線網路
Install
diff --git a/tools/sim/bridge/common.py b/tools/sim/bridge/common.py
index 464ea08823..360fdc0e68 100644
--- a/tools/sim/bridge/common.py
+++ b/tools/sim/bridge/common.py
@@ -19,7 +19,7 @@ from openpilot.tools.sim.lib.simulated_sensors import SimulatedSensors
def rk_loop(function, hz, exit_event: threading.Event):
- rk = Ratekeeper(hz)
+ rk = Ratekeeper(hz, None)
while not exit_event.is_set():
function()
rk.keep_time()
diff --git a/tools/sim/bridge/metadrive.py b/tools/sim/bridge/metadrive.py
new file mode 100644
index 0000000000..f7b937359e
--- /dev/null
+++ b/tools/sim/bridge/metadrive.py
@@ -0,0 +1,156 @@
+import math
+import numpy as np
+import time
+
+from openpilot.tools.sim.bridge.common import World, SimulatorBridge
+from openpilot.tools.sim.lib.common import vec3, SimulatorState
+from openpilot.tools.sim.lib.camerad import W, H
+
+
+def apply_metadrive_patches():
+ from metadrive.engine.core.engine_core import EngineCore
+ from metadrive.engine.core.image_buffer import ImageBuffer
+ from metadrive.obs.image_obs import ImageObservation
+
+ # By default, metadrive won't try to use cuda images unless it's used as a sensor for vehicles, so patch that in
+ def add_image_sensor_patched(self, name: str, cls, args):
+ if self.global_config["image_on_cuda"]:# and name == self.global_config["vehicle_config"]["image_source"]:
+ sensor = cls(*args, self, cuda=True)
+ else:
+ sensor = cls(*args, self, cuda=False)
+ assert isinstance(sensor, ImageBuffer), "This API is for adding image sensor"
+ self.sensors[name] = sensor
+
+ EngineCore.add_image_sensor = add_image_sensor_patched
+
+ # we aren't going to use the built-in observation stack, so disable it to save time
+ def observe_patched(self, vehicle):
+ return self.state
+
+ ImageObservation.observe = observe_patched
+
+
+class MetaDriveWorld(World):
+ def __init__(self, env, ticks_per_frame: float, dual_camera = False):
+ super().__init__(dual_camera)
+ self.env = env
+ self.ticks_per_frame = ticks_per_frame
+ self.dual_camera = dual_camera
+
+ self.steer_ratio = 15
+
+ self.vc = [0.0,0.0]
+
+ self.reset_time = 0
+
+ def get_cam_as_rgb(self, cam):
+ cam = self.env.engine.sensors[cam]
+ img = cam.perceive(self.env.vehicle, clip=False)
+ if type(img) != np.ndarray:
+ img = img.get() # convert cupy array to numpy
+ return img
+
+ def apply_controls(self, steer_angle, throttle_out, brake_out):
+ steer_metadrive = steer_angle * 1 / (self.env.vehicle.MAX_STEERING * self.steer_ratio)
+ steer_metadrive = np.clip(steer_metadrive, -1, 1)
+
+ if (time.monotonic() - self.reset_time) > 5:
+ self.vc[0] = steer_metadrive
+
+ if throttle_out:
+ self.vc[1] = throttle_out/10
+ else:
+ self.vc[1] = -brake_out
+ else:
+ self.vc[0] = 0
+ self.vc[1] = 0
+
+ def read_sensors(self, state: SimulatorState):
+ state.velocity = vec3(x=float(self.env.vehicle.velocity[0]), y=float(self.env.vehicle.velocity[1]), z=0)
+ state.gps.from_xy(self.env.vehicle.position)
+ state.bearing = float(math.degrees(self.env.vehicle.heading_theta))
+ state.steering_angle = self.env.vehicle.steering * self.env.vehicle.MAX_STEERING
+ state.valid = True
+
+ def read_cameras(self):
+ if self.dual_camera:
+ self.wide_road_image = self.get_cam_as_rgb("rgb_wide")
+ self.road_image = self.get_cam_as_rgb("rgb_road")
+
+ def tick(self):
+ obs, _, terminated, _, info = self.env.step(self.vc)
+
+ if terminated:
+ self.env.reset()
+ self.reset_time = time.monotonic()
+
+ def close(self):
+ pass
+
+
+class MetaDriveBridge(SimulatorBridge):
+ TICKS_PER_FRAME = 2
+
+ def __init__(self, args):
+ self.should_render = False
+
+ super(MetaDriveBridge, self).__init__(args)
+
+ def spawn_world(self):
+ print("----------------------------------------------------------")
+ print("---- Spawning Metadrive world, this might take awhile ----")
+ print("----------------------------------------------------------")
+ from metadrive.component.sensors.rgb_camera import RGBCamera
+ from metadrive.component.sensors.base_camera import _cuda_enable
+ from metadrive.envs.metadrive_env import MetaDriveEnv
+ from panda3d.core import Vec3
+
+ apply_metadrive_patches()
+
+ C3_POSITION = Vec3(0, 0, 1)
+
+ class RGBCameraWide(RGBCamera):
+ def __init__(self, *args, **kwargs):
+ super(RGBCameraWide, self).__init__(*args, **kwargs)
+ cam = self.get_cam()
+ cam.setPos(C3_POSITION)
+ lens = self.get_lens()
+ lens.setFov(160)
+
+ class RGBCameraRoad(RGBCamera):
+ def __init__(self, *args, **kwargs):
+ super(RGBCameraRoad, self).__init__(*args, **kwargs)
+ cam = self.get_cam()
+ cam.setPos(C3_POSITION)
+ lens = self.get_lens()
+ lens.setFov(40)
+
+ sensors = {
+ "rgb_road": (RGBCameraRoad, W, H, )
+ }
+
+ if self.dual_camera:
+ sensors["rgb_wide"] = (RGBCameraWide, W, H)
+
+ env = MetaDriveEnv(
+ dict(
+ use_render=self.should_render,
+ vehicle_config=dict(
+ enable_reverse=False,
+ image_source="rgb_road",
+ spawn_longitude=15
+ ),
+ sensors=sensors,
+ image_on_cuda=_cuda_enable,
+ image_observation=True,
+ interface_panel=[],
+ out_of_route_done=False,
+ on_continuous_line_done=False,
+ crash_vehicle_done=False,
+ crash_object_done=False,
+ )
+ )
+
+ env.reset()
+
+ return MetaDriveWorld(env, self.TICKS_PER_FRAME)
\ No newline at end of file
diff --git a/tools/sim/lib/simulated_car.py b/tools/sim/lib/simulated_car.py
index 7cd01e1610..41b58063b9 100644
--- a/tools/sim/lib/simulated_car.py
+++ b/tools/sim/lib/simulated_car.py
@@ -107,6 +107,8 @@ class SimulatedCar:
def update(self, simulator_state: SimulatorState):
self.send_can_messages(simulator_state)
- self.send_panda_state(simulator_state)
+
+ if self.idx % 50 == 0: # only send panda states at 2hz
+ self.send_panda_state(simulator_state)
self.idx += 1
\ No newline at end of file
diff --git a/tools/sim/run_bridge.py b/tools/sim/run_bridge.py
index 8e6dc8f2ef..e58cf5f0af 100755
--- a/tools/sim/run_bridge.py
+++ b/tools/sim/run_bridge.py
@@ -1,11 +1,13 @@
#!/usr/bin/env python
import argparse
+import os
from typing import Any
from multiprocessing import Queue
from openpilot.tools.sim.bridge.common import SimulatorBridge
from openpilot.tools.sim.bridge.carla import CarlaBridge
+from openpilot.tools.sim.bridge.metadrive import MetaDriveBridge
def parse_args(add_args=None):
@@ -18,7 +20,7 @@ def parse_args(add_args=None):
# Carla specific
parser.add_argument('--town', type=str, default='Town04_Opt')
parser.add_argument('--spawn_point', dest='num_selected_spawn_point', type=int, default=16)
- parser.add_argument('--host', dest='host', type=str, default='127.0.0.1')
+ parser.add_argument('--host', dest='host', type=str, default=os.environ.get("CARLA_HOST", '127.0.0.1'))
parser.add_argument('--port', dest='port', type=int, default=2000)
return parser.parse_args(add_args)
@@ -30,6 +32,8 @@ if __name__ == "__main__":
simulator_bridge: SimulatorBridge
if args.simulator == "carla":
simulator_bridge = CarlaBridge(args)
+ elif args.simulator == "metadrive":
+ simulator_bridge = MetaDriveBridge(args)
else:
raise AssertionError("simulator type not supported")
p = simulator_bridge.run(q)
diff --git a/tools/sim/tests/test_carla_bridge.py b/tools/sim/tests/test_carla_bridge.py
new file mode 100755
index 0000000000..a2b38d11fe
--- /dev/null
+++ b/tools/sim/tests/test_carla_bridge.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+import subprocess
+import time
+import unittest
+
+from openpilot.selfdrive.manager.helpers import unblock_stdout
+from openpilot.tools.sim.run_bridge import parse_args
+from openpilot.tools.sim.bridge.carla import CarlaBridge
+from openpilot.tools.sim.tests.test_sim_bridge import SIM_DIR, TestSimBridgeBase
+
+
+class TestCarlaBridge(TestSimBridgeBase):
+ """
+ Tests need Carla simulator to run
+ """
+ carla_process = None
+
+ def setUp(self):
+ super().setUp()
+
+ # We want to make sure that carla_sim docker isn't still running.
+ subprocess.run("docker rm -f carla_sim", shell=True, stderr=subprocess.PIPE, check=False)
+ self.carla_process = subprocess.Popen("./start_carla.sh", cwd=SIM_DIR)
+
+ # Too many lagging messages in bridge.py can cause a crash. This prevents it.
+ unblock_stdout()
+ # Wait 10 seconds to startup carla
+ time.sleep(10)
+
+ def create_bridge(self):
+ return CarlaBridge(parse_args([]))
+
+ def tearDown(self):
+ super().tearDown()
+
+ # Stop carla simulator by removing docker container
+ subprocess.run("docker rm -f carla_sim", shell=True, stderr=subprocess.PIPE, check=False)
+ if self.carla_process is not None:
+ self.carla_process.wait()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tools/sim/tests/test_metadrive_bridge.py b/tools/sim/tests/test_metadrive_bridge.py
new file mode 100755
index 0000000000..175d3758ff
--- /dev/null
+++ b/tools/sim/tests/test_metadrive_bridge.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python3
+import unittest
+
+from openpilot.tools.sim.run_bridge import parse_args
+from openpilot.tools.sim.bridge.metadrive import MetaDriveBridge
+from openpilot.tools.sim.tests.test_sim_bridge import TestSimBridgeBase
+
+
+class TestMetaDriveBridge(TestSimBridgeBase):
+ def create_bridge(self):
+ return MetaDriveBridge(parse_args([]))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tools/sim/tests/test_carla_integration.py b/tools/sim/tests/test_sim_bridge.py
old mode 100755
new mode 100644
similarity index 71%
rename from tools/sim/tests/test_carla_integration.py
rename to tools/sim/tests/test_sim_bridge.py
index b5a60ee0e3..b00527b322
--- a/tools/sim/tests/test_carla_integration.py
+++ b/tools/sim/tests/test_sim_bridge.py
@@ -1,40 +1,24 @@
-#!/usr/bin/env python3
+import os
import subprocess
import time
import unittest
-import os
+
from multiprocessing import Queue
from cereal import messaging
from openpilot.common.basedir import BASEDIR
-from openpilot.selfdrive.manager.helpers import unblock_stdout
-from openpilot.tools.sim.run_bridge import parse_args
-from openpilot.tools.sim.bridge.carla import CarlaBridge
-
-CI = "CI" in os.environ
SIM_DIR = os.path.join(BASEDIR, "tools/sim")
-class TestCarlaIntegration(unittest.TestCase):
- """
- Tests need Carla simulator to run
- """
- processes = None
- carla_process = None
+class TestSimBridgeBase(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ if cls is TestSimBridgeBase:
+ raise unittest.SkipTest("Don't run this base class, run test_carla_bridge.py instead")
def setUp(self):
self.processes = []
- if not CI:
- # We want to make sure that carla_sim docker isn't still running.
- subprocess.run("docker rm -f carla_sim", shell=True, stderr=subprocess.PIPE, check=False)
- self.carla_process = subprocess.Popen("./start_carla.sh", cwd=SIM_DIR)
-
- # Too many lagging messages in bridge.py can cause a crash. This prevents it.
- unblock_stdout()
- # Wait 10 seconds to startup carla
- time.sleep(10)
-
def test_engage(self):
# Startup manager and bridge.py. Check processes are running, then engage and verify.
p_manager = subprocess.Popen("./launch_openpilot.sh", cwd=SIM_DIR)
@@ -42,7 +26,7 @@ class TestCarlaIntegration(unittest.TestCase):
sm = messaging.SubMaster(['controlsState', 'carEvents', 'managerState'])
q = Queue()
- carla_bridge = CarlaBridge(parse_args([]))
+ carla_bridge = self.create_bridge()
p_bridge = carla_bridge.run(q, retries=10)
self.processes.append(p_bridge)
@@ -99,11 +83,6 @@ class TestCarlaIntegration(unittest.TestCase):
else:
p.join(15)
- # Stop carla simulator by removing docker container
- subprocess.run("docker rm -f carla_sim", shell=True, stderr=subprocess.PIPE, check=False)
- if self.carla_process is not None:
- self.carla_process.wait()
-
if __name__ == "__main__":
unittest.main()