diff --git a/.github/workflows/selfdrive_tests.yaml b/.github/workflows/selfdrive_tests.yaml
index 9456914371..6e17f5a480 100644
--- a/.github/workflows/selfdrive_tests.yaml
+++ b/.github/workflows/selfdrive_tests.yaml
@@ -48,7 +48,7 @@ jobs:
- uses: ./.github/workflows/setup-with-retry
- name: Check submodules
if: github.ref == 'refs/heads/master' && github.repository == 'commaai/openpilot'
- timeout-minutes: 1
+ timeout-minutes: 3
run: release/check-submodules.sh
- name: Build openpilot and run checks
timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 10 || 30) }} # allow more time when we missed the scons cache
@@ -56,7 +56,7 @@ jobs:
cd $STRIPPED_DIR
${{ env.RUN }} "python3 system/manager/build.py"
- name: Run tests
- timeout-minutes: 3
+ timeout-minutes: 1
run: |
cd $STRIPPED_DIR
${{ env.RUN }} "release/check-dirty.sh && \
@@ -76,7 +76,9 @@ jobs:
((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') && 'namespace-profile-arm64-2x8' || 'ubuntu-latest' }}
+ runs-on: ${{ ((matrix.arch == 'aarch64') && 'namespace-profile-arm64-2x8') ||
+ ((matrix.arch == 'x86_64') && ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16') ||
+ 'ubuntu-latest'}}
steps:
- uses: actions/checkout@v4
with:
@@ -144,11 +146,12 @@ jobs:
PYTHONWARNINGS: default
steps:
- uses: actions/checkout@v4
- - name: Setup
- run: tools/op.sh setup
+ with:
+ submodules: true
+ - uses: ./.github/workflows/setup-with-retry
- name: Static analysis
timeout-minutes: 1
- run: tools/op.sh lint
+ run: ${{ env.RUN }} "scripts/lint/lint.sh"
unit_tests:
name: unit tests
@@ -327,24 +330,54 @@ jobs:
comment_id: ${{ steps.fc.outputs.comment-id }}
})
+ simulator_driving:
+ name: simulator driving
+ runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
+ ((github.event_name != 'pull_request') ||
+ (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ submodules: true
+ - uses: ./.github/workflows/setup-with-retry
+ - name: Build openpilot
+ run: |
+ ${{ env.RUN }} "scons -j$(nproc)"
+ - name: Driving test
+ timeout-minutes: 1
+ run: |
+ ${{ env.RUN }} "source selfdrive/test/setup_xvfb.sh && \
+ source selfdrive/test/setup_vsound.sh && \
+ CI=1 pytest tools/sim/tests/test_metadrive_bridge.py"
+
create_ui_report:
# This job name needs to be the same as UI_JOB_NAME in ui_preview.yaml
name: Create UI Report
- runs-on: ubuntu-latest
+ runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
+ ((github.event_name != 'pull_request') ||
+ (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
+ - name: caching frames
+ id: frames-cache
+ uses: actions/cache@v4
+ with:
+ path: .ci_cache/comma_download_cache
+ key: ui_screenshots_test_${{ hashFiles('selfdrive/ui/tests/test_ui/run.py') }}
- name: Build openpilot
run: ${{ env.RUN }} "scons -j$(nproc)"
- name: Create Test Report
+ timeout-minutes: ${{ ((steps.frames-cache.outputs.cache-hit == 'true') && 1 || 3) }}
run: >
${{ env.RUN }} "PYTHONWARNINGS=ignore &&
source selfdrive/test/setup_xvfb.sh &&
- python3 selfdrive/ui/tests/test_ui/run.py"
+ CACHE_ROOT=/tmp/comma_download_cache python3 selfdrive/ui/tests/test_ui/run.py &&
+ chmod -R 777 /tmp/comma_download_cache"
- name: Upload Test Report
uses: actions/upload-artifact@v4
with:
- name: report-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }}
+ name: report-${{ inputs.run_number || '1' }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }}
path: selfdrive/ui/tests/test_ui/report_1/screenshots
diff --git a/.github/workflows/tools_tests.yaml b/.github/workflows/tools_tests.yaml
index c1c3552472..493671051f 100644
--- a/.github/workflows/tools_tests.yaml
+++ b/.github/workflows/tools_tests.yaml
@@ -25,24 +25,6 @@ env:
jobs:
- simulator_driving:
- name: simulator driving
- runs-on: ubuntu-latest
- timeout-minutes: 20
- steps:
- - uses: actions/checkout@v4
- with:
- submodules: true
- - uses: ./.github/workflows/setup-with-retry
- - name: Build openpilot
- run: |
- ${{ env.RUN }} "scons -j$(nproc)"
- - name: Run bridge test
- run: |
- ${{ env.RUN }} "source selfdrive/test/setup_xvfb.sh && \
- source selfdrive/test/setup_vsound.sh && \
- CI=1 pytest tools/sim/tests/test_metadrive_bridge.py"
-
devcontainer:
name: devcontainer
runs-on: ubuntu-latest
diff --git a/.github/workflows/ui_preview.yaml b/.github/workflows/ui_preview.yaml
index 4f25a71452..1842ef21e9 100644
--- a/.github/workflows/ui_preview.yaml
+++ b/.github/workflows/ui_preview.yaml
@@ -52,7 +52,7 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
run_id: ${{ steps.get_run_id.outputs.run_id }}
search_artifacts: true
- name: report-${{ env.REPORT_NAME }}
+ name: report-1-${{ env.REPORT_NAME }}
path: ${{ github.workspace }}/pr_ui
- name: Getting master ui
diff --git a/docs/CARS.md b/docs/CARS.md
index 84efe3c041..44c9327378 100644
--- a/docs/CARS.md
+++ b/docs/CARS.md
@@ -30,7 +30,7 @@ A supported vehicle is one that just works when you install a comma device. All
|comma|body|All|openpilot|0 mph|0 mph|[](##)|[](##)|None||
|CUPRA|Ateca 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,12](#footnotes)|0 mph|0 mph|[](##)|[](##)|Parts
- 1 USB-C coupler
- 1 VW J533 connector
- 1 comma 3X
- 1 harness box
- 1 long OBD-C cable
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
|Dodge|Durango 2020-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|Parts
- 1 FCA connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
-|Ford|Bronco Sport 2021-23|Co-Pilot360 Assist+|openpilot available[1](#footnotes)|0 mph|0 mph|[](##)|[](##)|Parts
- 1 Ford Q3 connector
- 1 RJ45 cable (7 ft)
- 1 angled mount (8 degrees)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
+|Ford|Bronco Sport 2021-24|Co-Pilot360 Assist+|openpilot available[1](#footnotes)|0 mph|0 mph|[](##)|[](##)|Parts
- 1 Ford Q3 connector
- 1 RJ45 cable (7 ft)
- 1 angled mount (8 degrees)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
|Ford|Escape 2020-22|Co-Pilot360 Assist+|openpilot available[1](#footnotes)|0 mph|0 mph|[](##)|[](##)|Parts
- 1 Ford Q3 connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
|Ford|Escape Hybrid 2020-22|Co-Pilot360 Assist+|openpilot available[1](#footnotes)|0 mph|0 mph|[](##)|[](##)|Parts
- 1 Ford Q3 connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
|Ford|Escape Plug-in Hybrid 2020-22|Co-Pilot360 Assist+|openpilot available[1](#footnotes)|0 mph|0 mph|[](##)|[](##)|Parts
- 1 Ford Q3 connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
@@ -184,8 +184,8 @@ A supported vehicle is one that just works when you install a comma device. All
|Lexus|RX Hybrid 2017-19|All|openpilot available[2](#footnotes)|0 mph|0 mph|[](##)|[](##)|Parts
- 1 RJ45 cable (7 ft)
- 1 Toyota A connector
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
|Lexus|RX Hybrid 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|Parts
- 1 RJ45 cable (7 ft)
- 1 Toyota A connector
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
|Lexus|UX Hybrid 2019-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|Parts
- 1 RJ45 cable (7 ft)
- 1 Toyota A connector
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
-|Lincoln|Aviator 2020-23|Co-Pilot360 Plus|openpilot available[1](#footnotes)|0 mph|0 mph|[](##)|[](##)|Parts
- 1 Ford Q3 connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
-|Lincoln|Aviator Plug-in Hybrid 2020-23|Co-Pilot360 Plus|openpilot available[1](#footnotes)|0 mph|0 mph|[](##)|[](##)|Parts
- 1 Ford Q3 connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
+|Lincoln|Aviator 2020-24|Co-Pilot360 Plus|openpilot available[1](#footnotes)|0 mph|0 mph|[](##)|[](##)|Parts
- 1 Ford Q3 connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
+|Lincoln|Aviator Plug-in Hybrid 2020-24|Co-Pilot360 Plus|openpilot available[1](#footnotes)|0 mph|0 mph|[](##)|[](##)|Parts
- 1 Ford Q3 connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
|MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,12](#footnotes)|0 mph|31 mph|[](##)|[](##)|Parts
- 1 USB-C coupler
- 1 VW J533 connector
- 1 angled mount (8 degrees)
- 1 comma 3X
- 1 harness box
- 1 long OBD-C cable
- 1 right angle OBD-C cable (1.5 ft)
Buy Here |
|
|MAN|TGE 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,12](#footnotes)|0 mph|31 mph|[](##)|[](##)|Parts
- 1 USB-C coupler
- 1 VW J533 connector
- 1 angled mount (8 degrees)
- 1 comma 3X
- 1 harness box
- 1 long OBD-C cable
- 1 right angle OBD-C cable (1.5 ft)
Buy Here |
|
|Mazda|CX-5 2022-24|All|Stock|0 mph|0 mph|[](##)|[](##)|Parts
- 1 Mazda connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here ||
diff --git a/opendbc_repo b/opendbc_repo
index 4aae6d02be..c4114772ba 160000
--- a/opendbc_repo
+++ b/opendbc_repo
@@ -1 +1 @@
-Subproject commit 4aae6d02bece759b6f25666db6b9428ae5011161
+Subproject commit c4114772ba9d77bf03b97972611591e0bf8e4a25
diff --git a/panda b/panda
index 3066f93d8a..0b364ece1e 160000
--- a/panda
+++ b/panda
@@ -1 +1 @@
-Subproject commit 3066f93d8a1db92ac900e6ccc64ff68c154deafb
+Subproject commit 0b364ece1eafa2e66b71be7cade3fdfb56a3014e
diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py
index fa6d5542bd..65e1421d77 100755
--- a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py
+++ b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py
@@ -347,7 +347,8 @@ class LongitudinalMpc:
lead_1_obstacle = lead_xv_1[:,0] + get_stopped_equivalence_factor(lead_xv_1[:,1])
self.params[:,0] = ACCEL_MIN
- self.params[:,1] = self.max_a
+ # negative accel constraint causes problems because negative speed is not allowed
+ self.params[:,1] = max(0.0, self.max_a)
# Update in ACC mode or ACC/e2e blend
if self.mode == 'acc':
@@ -356,6 +357,7 @@ class LongitudinalMpc:
# Fake an obstacle for cruise, this ensures smooth acceleration to set speed
# when the leads are no factor.
v_lower = v_ego + (T_IDXS * self.cruise_min_a * 1.05)
+ # TODO does this make sense when max_a is negative?
v_upper = v_ego + (T_IDXS * self.max_a * 1.05)
v_cruise_clipped = np.clip(v_cruise * np.ones(N+1),
v_lower,
diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py
index 5f47cebb1f..f1637d960c 100755
--- a/selfdrive/controls/lib/longitudinal_planner.py
+++ b/selfdrive/controls/lib/longitudinal_planner.py
@@ -22,7 +22,7 @@ A_CRUISE_MAX_VALS = [1.6, 1.2, 0.8, 0.6]
A_CRUISE_MAX_BP = [0., 10.0, 25., 40.]
CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N]
ALLOW_THROTTLE_THRESHOLD = 0.5
-ACCEL_LIMIT_MARGIN = 0.05
+MIN_ALLOW_THROTTLE_SPEED = 2.5
# Lookup table for turns
_A_TOTAL_MAX_V = [1.7, 3.2]
@@ -151,12 +151,12 @@ class LongitudinalPlanner:
self.v_model_error = get_speed_error(sm['modelV2'], v_ego)
x, v, a, j, throttle_prob = self.parse_model(sm['modelV2'], self.v_model_error)
# Don't clip at low speeds since throttle_prob doesn't account for creep
- self.allow_throttle = throttle_prob > ALLOW_THROTTLE_THRESHOLD or v_ego <= 5.0
+ self.allow_throttle = throttle_prob > ALLOW_THROTTLE_THRESHOLD or v_ego <= MIN_ALLOW_THROTTLE_SPEED
if not self.allow_throttle:
- # MPC breaks when accel limits would cause negative velocity within the MPC horizon, so we clip the max accel limit at vEgo/T_MAX plus a bit of margin
- clipped_accel_coast = max(accel_coast, accel_limits_turns[0], -v_ego / T_IDXS_MPC[-1] + ACCEL_LIMIT_MARGIN)
- accel_limits_turns[1] = min(accel_limits_turns[1], clipped_accel_coast)
+ clipped_accel_coast = max(accel_coast, accel_limits_turns[0])
+ clipped_accel_coast_interp = interp(v_ego, [MIN_ALLOW_THROTTLE_SPEED, MIN_ALLOW_THROTTLE_SPEED*2], [accel_limits_turns[1], clipped_accel_coast])
+ accel_limits_turns[1] = min(accel_limits_turns[1], clipped_accel_coast_interp)
if force_slow_decel:
v_cruise = 0.0
diff --git a/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py b/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py
index 7eea44aae6..4bc1ebba8f 100644
--- a/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py
+++ b/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py
@@ -108,18 +108,6 @@ def create_maneuvers(kwargs):
breakpoints=[0.0, 2., 2.01],
**kwargs,
),
- Maneuver(
- "slow to 5m/s with allow_throttle = False and pitch = +0.1",
- duration=25.,
- initial_speed=20.,
- lead_relevancy=False,
- prob_throttle_values=[1., 0., 0.],
- cruise_values=[20., 20., 20.],
- pitch_values=[0., 0.1, 0.1],
- breakpoints=[0.0, 2., 2.01],
- ensure_slowdown=True,
- **kwargs,
- ),
Maneuver(
"approach slower cut-in car at 20m/s",
duration=20.,
@@ -163,6 +151,20 @@ def create_maneuvers(kwargs):
**kwargs,
),
]
+ if not kwargs['e2e']:
+ # allow_throttle won't trigger with e2e
+ maneuvers.append(Maneuver(
+ "slow to 5m/s with allow_throttle = False and pitch = +0.1",
+ duration=30.,
+ initial_speed=20.,
+ lead_relevancy=False,
+ prob_throttle_values=[1., 0., 0.],
+ cruise_values=[20., 20., 20.],
+ pitch_values=[0., 0.1, 0.1],
+ breakpoints=[0.0, 2., 2.01],
+ ensure_slowdown=True,
+ **kwargs,
+ ))
if not kwargs['force_decel']:
# controls relies on planner commanding to move for stock-ACC resume spamming
maneuvers.append(Maneuver(
diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit
index 6842530946..2f565836fd 100644
--- a/selfdrive/test/process_replay/ref_commit
+++ b/selfdrive/test/process_replay/ref_commit
@@ -1 +1 @@
-8f9dba78b0a2a4fbf8122f61d49e9529dba9b3b4
\ No newline at end of file
+992ac80ef848afb85562ca24b1c5a3d410aacd05
\ No newline at end of file
diff --git a/selfdrive/ui/tests/test_ui/run.py b/selfdrive/ui/tests/test_ui/run.py
index e6fd9a016a..8cd5f1930d 100644
--- a/selfdrive/ui/tests/test_ui/run.py
+++ b/selfdrive/ui/tests/test_ui/run.py
@@ -3,11 +3,10 @@ import capnp
import pathlib
import shutil
import sys
-import jinja2
-import matplotlib.pyplot as plt
-import numpy as np
import os
import pywinctl
+import pyautogui
+import pickle
import time
from cereal import log
@@ -23,8 +22,9 @@ from openpilot.selfdrive.test.process_replay.migration import migrate, migrate_c
from openpilot.tools.lib.logreader import LogReader
from openpilot.tools.lib.framereader import FrameReader
from openpilot.tools.lib.route import Route
+from openpilot.tools.lib.cache import DEFAULT_CACHE_DIR
-UI_DELAY = 0.5 # may be slower on CI?
+UI_DELAY = 0.1 # may be slower on CI?
TEST_ROUTE = "a2a0ccea32023010|2023-07-27--13-01-19"
STREAMS: list[tuple[VisionStreamType, CameraConfig, bytes]] = []
@@ -222,41 +222,20 @@ class TestUI:
print(f"failed to find ui window, assuming that it's in the top left (for Xvfb) {e}")
self.ui = namedtuple("bb", ["left", "top", "width", "height"])(0,0,2160,1080)
- def screenshot(self):
- import pyautogui
- im = pyautogui.screenshot(region=(self.ui.left, self.ui.top, self.ui.width, self.ui.height))
+ def screenshot(self, name):
+ im = pyautogui.screenshot(SCREENSHOTS_DIR / f"{name}.png", region=(self.ui.left, self.ui.top, self.ui.width, self.ui.height))
assert im.width == 2160
assert im.height == 1080
- img = np.array(im)
- im.close()
- return img
def click(self, x, y, *args, **kwargs):
- import pyautogui
pyautogui.click(self.ui.left + x, self.ui.top + y, *args, **kwargs)
time.sleep(UI_DELAY) # give enough time for the UI to react
@with_processes(["ui"])
def test_ui(self, name, setup_case):
self.setup()
-
setup_case(self.click, self.pm)
-
- im = self.screenshot()
- plt.imsave(SCREENSHOTS_DIR / f"{name}.png", im)
-
-
-def create_html_report():
- OUTPUT_FILE = TEST_OUTPUT_DIR / "index.html"
-
- with open(TEST_DIR / "template.html") as f:
- template = jinja2.Template(f.read())
-
- cases = {f.stem: (str(f.relative_to(TEST_OUTPUT_DIR)), "reference.png") for f in SCREENSHOTS_DIR.glob("*.png")}
- cases = dict(sorted(cases.items()))
-
- with open(OUTPUT_FILE, "w") as f:
- f.write(template.render(cases=cases))
+ self.screenshot(name)
def create_screenshots():
if TEST_OUTPUT_DIR.exists():
@@ -277,13 +256,23 @@ def create_screenshots():
break
cam = DEVICE_CAMERAS[("tici", "ar0231")]
- road_img = FrameReader(route.camera_paths()[segnum]).get(0, pix_fmt="nv12")[0]
- STREAMS.append((VisionStreamType.VISION_STREAM_ROAD, cam.fcam, road_img.flatten().tobytes()))
- wide_road_img = FrameReader(route.ecamera_paths()[segnum]).get(0, pix_fmt="nv12")[0]
- STREAMS.append((VisionStreamType.VISION_STREAM_WIDE_ROAD, cam.ecam, wide_road_img.flatten().tobytes()))
+ frames_cache = f'{DEFAULT_CACHE_DIR}/ui_frames'
+ if os.path.isfile(frames_cache):
+ with open(frames_cache, 'rb') as f:
+ frames = pickle.load(f)
+ road_img = frames[0]
+ wide_road_img = frames[1]
+ driver_img = frames[2]
+ else:
+ with open(frames_cache, 'wb') as f:
+ road_img = FrameReader(route.camera_paths()[segnum]).get(0, pix_fmt="nv12")[0]
+ wide_road_img = FrameReader(route.ecamera_paths()[segnum]).get(0, pix_fmt="nv12")[0]
+ driver_img = FrameReader(route.dcamera_paths()[segnum]).get(0, pix_fmt="nv12")[0]
+ pickle.dump([road_img, wide_road_img, driver_img], f)
- driver_img = FrameReader(route.dcamera_paths()[segnum]).get(0, pix_fmt="nv12")[0]
+ STREAMS.append((VisionStreamType.VISION_STREAM_ROAD, cam.fcam, road_img.flatten().tobytes()))
+ STREAMS.append((VisionStreamType.VISION_STREAM_WIDE_ROAD, cam.ecam, wide_road_img.flatten().tobytes()))
STREAMS.append((VisionStreamType.VISION_STREAM_DRIVER, cam.dcam, driver_img.flatten().tobytes()))
t = TestUI()
@@ -302,6 +291,3 @@ def create_screenshots():
if __name__ == "__main__":
print("creating test screenshots")
create_screenshots()
-
- print("creating html report")
- create_html_report()
diff --git a/system/camerad/cameras/ife.h b/system/camerad/cameras/ife.h
index 70a448dd1f..1616196a3f 100644
--- a/system/camerad/cameras/ife.h
+++ b/system/camerad/cameras/ife.h
@@ -167,16 +167,16 @@ int build_initial_config(uint8_t *dst, const SensorInfo *s, std::vector color_correct_matrix; // 3x3
std::vector gamma_lut_rgb; // gamma LUTs are length 64 * sizeof(uint32_t); same for r/g/b here
+ void prepare_gamma_lut() {
+ for (int i = 0; i < 64; i++) {
+ gamma_lut_rgb[i] |= ((uint32_t)(gamma_lut_rgb[i+1] - gamma_lut_rgb[i]) << 10);
+ }
+ gamma_lut_rgb.pop_back();
+ }
std::vector linearization_lut; // length 288
std::vector linearization_pts; // length 4
std::vector vignetting_lut; // 2x length 884
diff --git a/system/hardware/tici/amplifier.py b/system/hardware/tici/amplifier.py
index af82067467..f6b29ec0ce 100755
--- a/system/hardware/tici/amplifier.py
+++ b/system/hardware/tici/amplifier.py
@@ -125,13 +125,15 @@ class Amplifier:
def set_configs(self, configs: list[AmpConfig]) -> bool:
# retry in case panda is using the amp
tries = 15
- for i in range(15):
+ backoff = 0.
+ for i in range(tries):
try:
self._set_configs(configs)
return True
except OSError:
+ backoff += 0.1
+ time.sleep(backoff)
print(f"Failed to set amp config, {tries - i - 1} retries left")
- time.sleep(0.02)
return False
def set_global_shutdown(self, amp_disabled: bool) -> bool:
diff --git a/tools/sim/bridge/metadrive/metadrive_world.py b/tools/sim/bridge/metadrive/metadrive_world.py
index 5bb4555dc1..a34d270994 100644
--- a/tools/sim/bridge/metadrive/metadrive_world.py
+++ b/tools/sim/bridge/metadrive/metadrive_world.py
@@ -105,7 +105,7 @@ class MetaDriveWorld(World):
if x_dist >= dist_threshold or y_dist >= dist_threshold: # position not the same during staying still, > threshold is considered moving
self.distance_moved += x_dist + y_dist
- time_check_threshold = 30
+ time_check_threshold = 15
current_time = time.monotonic()
since_last_check = current_time - self.last_check_timestamp
if since_last_check >= time_check_threshold:
diff --git a/tools/sim/tests/test_metadrive_bridge.py b/tools/sim/tests/test_metadrive_bridge.py
index 8849e901cb..04ce5d584f 100644
--- a/tools/sim/tests/test_metadrive_bridge.py
+++ b/tools/sim/tests/test_metadrive_bridge.py
@@ -12,10 +12,7 @@ from openpilot.tools.sim.tests.test_sim_bridge import TestSimBridgeBase
class TestMetaDriveBridge(TestSimBridgeBase):
@pytest.fixture(autouse=True)
def setup_create_bridge(self, test_duration):
- # run bridge test for at least 60s, since not-moving check runs every 30s
- if test_duration < 60:
- test_duration = 60
- self.test_duration = test_duration
+ self.test_duration = 30
def create_bridge(self):
return MetaDriveBridge(False, False, self.test_duration, True)
diff --git a/tools/sim/tests/test_sim_bridge.py b/tools/sim/tests/test_sim_bridge.py
index 12f38b86c3..d58cddff7f 100644
--- a/tools/sim/tests/test_sim_bridge.py
+++ b/tools/sim/tests/test_sim_bridge.py
@@ -89,7 +89,4 @@ class TestSimBridgeBase:
p.terminate()
for p in reversed(self.processes):
- if isinstance(p, subprocess.Popen):
- p.wait(15)
- else:
- p.join(15)
+ p.kill()