diff --git a/.github/workflows/badges.yaml b/.github/workflows/badges.yaml
index 68a13398f6..223c734863 100644
--- a/.github/workflows/badges.yaml
+++ b/.github/workflows/badges.yaml
@@ -17,7 +17,8 @@ env:
jobs:
badges:
name: create badges
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
+ if: github.repository == 'commaai/openpilot'
steps:
- uses: actions/checkout@v3
with:
diff --git a/.github/workflows/prebuilt.yaml b/.github/workflows/prebuilt.yaml
index 99d9694f24..b659d4ceee 100644
--- a/.github/workflows/prebuilt.yaml
+++ b/.github/workflows/prebuilt.yaml
@@ -9,7 +9,7 @@ env:
BASE_IMAGE: openpilot-base
DOCKER_REGISTRY: ghcr.io/commaai
- DOCKER_LOGIN: docker login ghcr.io -u adeebshihadeh -p ${{ secrets.CONTAINER_TOKEN }}
+ DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
BUILD: |
docker pull $(grep -iohP '(?<=^from)\s+\S+' Dockerfile.openpilot_base) || true
docker pull $DOCKER_REGISTRY/$BASE_IMAGE:latest || true
diff --git a/.github/workflows/selfdrive_tests.yaml b/.github/workflows/selfdrive_tests.yaml
index 7800323198..7397e30f83 100644
--- a/.github/workflows/selfdrive_tests.yaml
+++ b/.github/workflows/selfdrive_tests.yaml
@@ -11,7 +11,7 @@ env:
DOCKER_REGISTRY: ghcr.io/commaai
AZURE_TOKEN: ${{ secrets.AZURE_COMMADATACI_OPENPILOTCI_TOKEN }}
- DOCKER_LOGIN: docker login ghcr.io -u adeebshihadeh -p ${{ secrets.CONTAINER_TOKEN }}
+ DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
BUILD: |
docker pull $(grep -iohP '(?<=^from)\s+\S+' Dockerfile.openpilot_base) || true
docker pull $DOCKER_REGISTRY/$BASE_IMAGE:latest || true
@@ -39,6 +39,8 @@ jobs:
with:
fetch-depth: 0
submodules: true
+ - name: Pull LFS
+ run: git lfs pull
- name: Check submodules
if: github.ref == 'refs/heads/master' && github.repository == 'commaai/openpilot'
run: release/check-submodules.sh
diff --git a/.github/workflows/tools_tests.yaml b/.github/workflows/tools_tests.yaml
index b2433fba8f..e93ce2bb39 100644
--- a/.github/workflows/tools_tests.yaml
+++ b/.github/workflows/tools_tests.yaml
@@ -7,7 +7,7 @@ env:
BASE_IMAGE: openpilot-base
CL_BASE_IMAGE: openpilot-base-cl
DOCKER_REGISTRY: ghcr.io/commaai
- DOCKER_LOGIN: docker login ghcr.io -u adeebshihadeh -p ${{ secrets.CONTAINER_TOKEN }}
+ DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
BUILD: |
docker pull $(grep -iohP '(?<=^from)\s+\S+' Dockerfile.openpilot_base) || true
diff --git a/Jenkinsfile b/Jenkinsfile
index b8ed52611d..6b05e81d79 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -127,7 +127,7 @@ pipeline {
steps {
phone_steps("tici2", [
["build", "cd selfdrive/manager && ./build.py"],
- ["test power draw", "python system/hardware/tici/test_power_draw.py"],
+ //["test power draw", "python system/hardware/tici/test_power_draw.py"],
["test boardd loopback", "python selfdrive/boardd/tests/test_boardd_loopback.py"],
["test loggerd", "python selfdrive/loggerd/tests/test_loggerd.py"],
["test encoder", "LD_LIBRARY_PATH=/usr/local/lib python selfdrive/loggerd/tests/test_encoder.py"],
diff --git a/docs/CARS.md b/docs/CARS.md
index a3455317fa..89705343bb 100644
--- a/docs/CARS.md
+++ b/docs/CARS.md
@@ -19,7 +19,7 @@ A supported vehicle is one that just works when you install a comma device. Ever
- [](##) - Limited ability to make tighter turns.
-# 200 Supported Cars
+# 201 Supported Cars
|Make|Model|Supported Package|openpilot ACC|Stop and Go|Steer to 0|Steering Torque|
|---|---|---|:---:|:---:|:---:|:---:|
@@ -95,11 +95,12 @@ A supported vehicle is one that just works when you install a comma device. Ever
|Jeep|Grand Cherokee 2016-18|Adaptive Cruise Control|[](##)|[](##)|[](##)|[](##)|
|Jeep|Grand Cherokee 2019-21|Adaptive Cruise Control|[](##)|[](##)|[](##)|[](##)|
|Kia|Ceed 2019|Smart Cruise Control (SCC) & LKAS|[](##)|[](##)|[](##)|[](##)|
-|Kia|EV6 2022[4](#footnotes)|All|[](##)|[](##)|[](##)|[](##)|
+|Kia|EV6 2022|All|[](##)|[](##)|[](##)|[](##)|
|Kia|Forte 2018|Smart Cruise Control (SCC) & LKAS|[](##)|[](##)|[](##)|[](##)|
|Kia|Forte 2019-21|All|[](##)|[](##)|[](##)|[](##)|
|Kia|K5 2021-22|Smart Cruise Control (SCC)|[](##)|[](##)|[](##)|[](##)|
-|Kia|Niro Electric 2019-20|All|[](##)|[](##)|[](##)|[](##)|
+|Kia|Niro Electric 2019|All|[](##)|[](##)|[](##)|[](##)|
+|Kia|Niro Electric 2020|All|[](##)|[](##)|[](##)|[](##)|
|Kia|Niro Electric 2021|All|[](##)|[](##)|[](##)|[](##)|
|Kia|Niro Electric 2022|All|[](##)|[](##)|[](##)|[](##)|
|Kia|Niro Hybrid 2021|Smart Cruise Control (SCC) & LKAS|[](##)|[](##)|[](##)|[](##)|
@@ -112,19 +113,19 @@ A supported vehicle is one that just works when you install a comma device. Ever
|Kia|Sorento 2019|Smart Cruise Control (SCC) & LKAS|[](##)|[](##)|[](##)|[](##)|
|Kia|Stinger 2018-20|Smart Cruise Control (SCC) & LKAS|[](##)|[](##)|[](##)|[](##)|
|Kia|Telluride 2020|All|[](##)|[](##)|[](##)|[](##)|
-|Lexus|CT Hybrid 2017-18|Lexus Safety System+|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Lexus|CT Hybrid 2017-18|Lexus Safety System+|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Lexus|ES 2019-22|All|[](##)|[](##)|[](##)|[](##)|
-|Lexus|ES Hybrid 2017-18|Lexus Safety System+|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Lexus|ES Hybrid 2017-18|Lexus Safety System+|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Lexus|ES Hybrid 2019-22|All|[](##)|[](##)|[](##)|[](##)|
|Lexus|IS 2017-19|All|[](##)|[](##)|[](##)|[](##)|
-|Lexus|NX 2018-19|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Lexus|NX 2018-19|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Lexus|NX 2020-21|All|[](##)|[](##)|[](##)|[](##)|
-|Lexus|NX Hybrid 2018-19|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Lexus|NX Hybrid 2018-19|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Lexus|NX Hybrid 2020-21|All|[](##)|[](##)|[](##)|[](##)|
|Lexus|RC 2017-20|All|[](##)|[](##)|[](##)|[](##)|
-|Lexus|RX 2016-18|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Lexus|RX 2016-18|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Lexus|RX 2020-22|All|[](##)|[](##)|[](##)|[](##)|
-|Lexus|RX Hybrid 2016-19|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Lexus|RX Hybrid 2016-19|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Lexus|RX Hybrid 2020-21|All|[](##)|[](##)|[](##)|[](##)|
|Lexus|UX Hybrid 2019-22|All|[](##)|[](##)|[](##)|[](##)|
|Mazda|CX-5 2022|All|[](##)|[](##)|[](##)|[](##)|
@@ -145,7 +146,7 @@ A supported vehicle is one that just works when you install a comma device. Ever
|Subaru|Outback 2020-22|All|[](##)|[](##)|[](##)|[](##)|
|Subaru|XV 2018-19|EyeSight Driver Assistance|[](##)|[](##)|[](##)|[](##)|
|Subaru|XV 2020-21|EyeSight Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Škoda|Kamiq 2021[7](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Škoda|Kamiq 2021[6](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
|Škoda|Karoq 2019-21|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
|Škoda|Kodiaq 2018-19|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
|Škoda|Octavia 2015, 2018-19|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
@@ -154,87 +155,86 @@ A supported vehicle is one that just works when you install a comma device. Ever
|Škoda|Superb 2015-18|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
|Toyota|Alphard 2019-20|All|[](##)|[](##)|[](##)|[](##)|
|Toyota|Alphard Hybrid 2021|All|[](##)|[](##)|[](##)|[](##)|
-|Toyota|Avalon 2016|Toyota Safety Sense P|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
-|Toyota|Avalon 2017-18|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
-|Toyota|Avalon 2019-21|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|Avalon 2016|Toyota Safety Sense P|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|Avalon 2017-18|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|Avalon 2019-21|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Toyota|Avalon 2022|All|[](##)|[](##)|[](##)|[](##)|
-|Toyota|Avalon Hybrid 2019-21|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|Avalon Hybrid 2019-21|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Toyota|Avalon Hybrid 2022|All|[](##)|[](##)|[](##)|[](##)|
|Toyota|C-HR 2017-21|All|[](##)|[](##)|[](##)|[](##)|
|Toyota|C-HR Hybrid 2017-19|All|[](##)|[](##)|[](##)|[](##)|
-|Toyota|Camry 2018-20|All|[](##)|[](##)[6](#footnotes)|[](##)|[](##)|
-|Toyota|Camry 2021-22|All|[](##)|[](##)[6](#footnotes)|[](##)|[](##)|
-|Toyota|Camry Hybrid 2018-20|All|[](##)|[](##)[6](#footnotes)|[](##)|[](##)|
+|Toyota|Camry 2018-20|All|[](##)|[](##)[5](#footnotes)|[](##)|[](##)|
+|Toyota|Camry 2021-22|All|[](##)|[](##)[5](#footnotes)|[](##)|[](##)|
+|Toyota|Camry Hybrid 2018-20|All|[](##)|[](##)[5](#footnotes)|[](##)|[](##)|
|Toyota|Camry Hybrid 2021-22|All|[](##)|[](##)|[](##)|[](##)|
-|Toyota|Corolla 2017-19|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|Corolla 2017-19|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Toyota|Corolla 2020-22|All|[](##)|[](##)|[](##)|[](##)|
|Toyota|Corolla Cross (Non-US only) 2020-21|All|[](##)|[](##)|[](##)|[](##)|
|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|[](##)|[](##)|[](##)|[](##)|
|Toyota|Corolla Hatchback 2019-22|All|[](##)|[](##)|[](##)|[](##)|
|Toyota|Corolla Hybrid 2020-22|All|[](##)|[](##)|[](##)|[](##)|
-|Toyota|Highlander 2017-19|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|Highlander 2017-19|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Toyota|Highlander 2020-22|All|[](##)|[](##)|[](##)|[](##)|
-|Toyota|Highlander Hybrid 2017-19|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|Highlander Hybrid 2017-19|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Toyota|Highlander Hybrid 2020-22|All|[](##)|[](##)|[](##)|[](##)|
|Toyota|Mirai 2021|All|[](##)|[](##)|[](##)|[](##)|
-|Toyota|Prius 2016|Toyota Safety Sense P|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
-|Toyota|Prius 2017-20|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|Prius 2016|Toyota Safety Sense P|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|Prius 2017-20|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Toyota|Prius 2021-22|All|[](##)|[](##)|[](##)|[](##)|
-|Toyota|Prius Prime 2017-20|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|Prius Prime 2017-20|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Toyota|Prius Prime 2021-22|All|[](##)|[](##)|[](##)|[](##)|
-|Toyota|Prius v 2017|Toyota Safety Sense P|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
-|Toyota|RAV4 2016|Toyota Safety Sense P|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
-|Toyota|RAV4 2017-18|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|Prius v 2017|Toyota Safety Sense P|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|RAV4 2016|Toyota Safety Sense P|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|RAV4 2017-18|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Toyota|RAV4 2019-21|All|[](##)|[](##)|[](##)|[](##)|
|Toyota|RAV4 2022|All|[](##)|[](##)|[](##)|[](##)|
-|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
-|Toyota|RAV4 Hybrid 2017-18|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
+|Toyota|RAV4 Hybrid 2017-18|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
|Toyota|RAV4 Hybrid 2019-21|All|[](##)|[](##)|[](##)|[](##)|
|Toyota|RAV4 Hybrid 2022|All|[](##)|[](##)|[](##)|[](##)|
-|Toyota|Sienna 2018-20|All|[](##)[5](#footnotes)|[](##)|[](##)|[](##)|
-|Volkswagen|Arteon 2018-22[9,10](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Arteon eHybrid 2020-22[9,10](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Arteon R 2020-22[9,10](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Atlas 2018-22[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Atlas Cross Sport 2021-22[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|California 2021[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Caravelle 2020[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|CC 2018-22[9,10](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Toyota|Sienna 2018-20|All|[](##)[4](#footnotes)|[](##)|[](##)|[](##)|
+|Volkswagen|Arteon 2018-22[8,9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Arteon eHybrid 2020-22[8,9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Arteon R 2020-22[8,9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Atlas 2018-22[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Atlas Cross Sport 2021-22[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|California 2021[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Caravelle 2020[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|CC 2018-22[8,9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
|Volkswagen|e-Golf 2014-20|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Golf 2015-20[10](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Golf 2015-20[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
|Volkswagen|Golf Alltrack 2015-19|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
|Volkswagen|Golf GTD 2015-20|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
|Volkswagen|Golf GTE 2015-20|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
|Volkswagen|Golf GTI 2015-21|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Golf R 2015-19[10](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Golf R 2015-19[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
|Volkswagen|Golf SportsVan 2015-20|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Jetta 2018-22[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Jetta GLI 2021-22[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Passat 2015-22[8,9,10](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Passat Alltrack 2015-22[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Passat GTE 2015-22[9,10](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Polo 2020-22[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Polo GTI 2020-22[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|T-Cross 2021[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|T-Roc 2021[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Taos 2022[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Teramont 2018-22[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Teramont Cross Sport 2021-22[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Teramont X 2021-22[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-|Volkswagen|Tiguan 2019-22[9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Jetta 2018-22[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Jetta GLI 2021-22[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Passat 2015-22[7,8,9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Passat Alltrack 2015-22[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Passat GTE 2015-22[8,9](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Polo 2020-22[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Polo GTI 2020-22[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|T-Cross 2021[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|T-Roc 2021[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Taos 2022[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Teramont 2018-22[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Teramont Cross Sport 2021-22[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Teramont X 2021-22[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
+|Volkswagen|Tiguan 2019-22[8](#footnotes)|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
|Volkswagen|Touran 2017|Driver Assistance|[](##)|[](##)|[](##)|[](##)|
-1Requires an OBD-II car harness and community built ASCM harness. NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).
+1Requires a community built ASCM harness. NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).
2Currently Requires a [harness box](https://comma.ai/shop/products/harness-box) and [community built GM camera harness](https://github.com/commaai/openpilot/wiki/GMCamHarness)
32019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph.
-4Requires a red panda and additional harness box.
-5When the Driver Support Unit (DSU) is disconnected, openpilot Adaptive Cruise Control (ACC) will replace stock Adaptive Cruise Control (ACC). NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).
-6openpilot operates above 28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control.
-7Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform.
-8Not including the USA/China market Passat, which is based on the (currently) unsupported PQ35/NMS platform.
-9Model-years 2021 and beyond may have a new camera harness design, which isn't yet available from the comma store. Before ordering, remove the Lane Assist camera cover and check to see if the connector is black (older design) or light brown (newer design). For the newer design, in the interim, choose "VW J533 Development" from the vehicle drop-down for a harness that integrates at the CAN gateway inside the dashboard.
-10Includes versions with extra rear cargo space (may be called Variant, Estate, SportWagen, Shooting Brake, etc.)
+4When the Driver Support Unit (DSU) is disconnected, openpilot Adaptive Cruise Control (ACC) will replace stock Adaptive Cruise Control (ACC). NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).
+5openpilot operates above 28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control.
+6Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform.
+7Not including the USA/China market Passat, which is based on the (currently) unsupported PQ35/NMS platform.
+8Model-years 2021 and beyond may have a new camera harness design, which isn't yet available from the comma store. Before ordering, remove the Lane Assist camera cover and check to see if the connector is black (older design) or light brown (newer design). For the newer design, in the interim, choose "VW J533 Development" from the vehicle drop-down for a harness that integrates at the CAN gateway inside the dashboard.
+9Includes versions with extra rear cargo space (may be called Variant, Estate, SportWagen, Shooting Brake, etc.)
## Community Maintained Cars
Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community Supported Models' section of each make [on our wiki](https://wiki.comma.ai/).
diff --git a/release/build_devel.sh b/release/build_devel.sh
index 9d8b06451b..f06e3102c8 100755
--- a/release/build_devel.sh
+++ b/release/build_devel.sh
@@ -69,6 +69,15 @@ date: $DATETIME
master commit: $GIT_HASH
"
+# ensure files are within GitHub's limit
+BIG_FILES="$(find . -type f -not -path './.git/*' -size +95M)"
+if [ ! -z "$BIG_FILES" ]; then
+ printf '\n\n\n'
+ echo "Found files exceeding GitHub's 100MB limit:"
+ echo "$BIG_FILES"
+ exit 1
+fi
+
if [ ! -z "$BRANCH" ]; then
echo "[-] Pushing to $BRANCH T=$SECONDS"
git push -f origin master-ci:$BRANCH
diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py
index 66c76bbcf3..c45a81a0ac 100644
--- a/selfdrive/car/chrysler/values.py
+++ b/selfdrive/car/chrysler/values.py
@@ -56,7 +56,7 @@ CAR_INFO: Dict[str, Optional[Union[ChryslerCarInfo, List[ChryslerCarInfo]]]] = {
],
CAR.JEEP_CHEROKEE: ChryslerCarInfo("Jeep Grand Cherokee 2016-18", video_link="https://www.youtube.com/watch?v=eLR9o2JkuRk"),
CAR.JEEP_CHEROKEE_2019: ChryslerCarInfo("Jeep Grand Cherokee 2019-21", video_link="https://www.youtube.com/watch?v=jBe4lWnRSu4"),
- CAR.RAM_1500: ChryslerCarInfo("Ram 1500 2019-22", harness=Harness.none),
+ CAR.RAM_1500: ChryslerCarInfo("Ram 1500 2019-22", harness=Harness.ram),
}
# Unique CAN messages:
@@ -107,6 +107,10 @@ FINGERPRINTS = {
}],
CAR.JEEP_CHEROKEE: [{
55: 8, 168: 8, 181: 8, 256: 4, 257: 5, 258: 8, 264: 8, 268: 8, 272: 6, 273: 6, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 4, 571: 3, 579: 8, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 656: 4, 658: 6, 660: 8, 671: 8, 672: 8, 676: 8, 678: 8, 680: 8, 683: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 738: 8, 746: 5, 752: 2, 754: 8, 760: 8, 761: 8, 764: 8, 766: 8, 773: 8, 776: 8, 779: 8, 782: 8, 783: 8, 784: 8, 785: 8, 788: 3, 792: 8, 799: 8, 800: 8, 804: 8, 806: 2, 808: 8, 810: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 840: 8, 844: 5, 847: 1, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 874: 2, 882: 8, 897: 8, 906: 8, 924: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 956: 8, 968: 8, 969: 4, 970: 8, 973: 8, 974: 5, 975: 8, 976: 8, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8, 1543: 8, 1562: 8, 2015: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8
+ },
+ # Based on c88f65eeaee4003a|2022-08-04--15-37-16
+ {
+ 257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 4, 571: 3, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 658: 6, 660: 8, 671: 8, 672: 8, 678: 8, 680: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 746: 5, 752: 2, 760: 8, 761: 8, 764: 8, 766: 8, 773: 8, 776: 8, 779: 8, 783: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 806: 2, 810: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 844: 5, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 924: 3, 937: 8, 947: 8, 948: 8, 969: 4, 974: 5, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8, 1216: 8, 1218: 8, 1220: 8, 1223: 8, 1235: 8, 1242: 8, 1252: 8, 1792: 8, 1798: 8, 1799: 8, 1810: 8, 1813: 8, 1824: 8, 1825: 8, 1840: 8, 1856: 8, 1858: 8, 1859: 8, 1860: 8, 1862: 8, 1863: 8, 1872: 8, 1875: 8, 1879: 8, 1882: 8, 1888: 8, 1892: 8, 1927: 8, 1937: 8, 1953: 8, 1968: 8, 1988: 8, 2000: 8, 2001: 8, 2004: 8, 2015: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8
}],
CAR.JEEP_CHEROKEE_2019: [{
# Jeep Grand Cherokee 2019, including most 2020 models
@@ -138,7 +142,7 @@ FW_VERSIONS = {
b'68535469AB',
b'68438454AC',
],
- (Ecu.fwdCamera, 0x753, None): [
+ (Ecu.fwdRadar, 0x753, None): [
b'68320950AL',
b'68320950AJ',
b'68454268AB',
diff --git a/selfdrive/car/docs_definitions.py b/selfdrive/car/docs_definitions.py
index 0215b8085c..86940a4e21 100644
--- a/selfdrive/car/docs_definitions.py
+++ b/selfdrive/car/docs_definitions.py
@@ -188,6 +188,7 @@ class Harness(Enum):
toyota = "Toyota"
subaru = "Subaru"
fca = "FCA"
+ ram = "Ram"
vw = "VW"
j533 = "J533"
hyundai_a = "Hyundai A"
diff --git a/selfdrive/car/gm/carcontroller.py b/selfdrive/car/gm/carcontroller.py
index 3657a3e056..ae74eaafd6 100644
--- a/selfdrive/car/gm/carcontroller.py
+++ b/selfdrive/car/gm/carcontroller.py
@@ -5,7 +5,7 @@ from common.realtime import DT_CTRL
from opendbc.can.packer import CANPacker
from selfdrive.car import apply_std_steer_torque_limits
from selfdrive.car.gm import gmcan
-from selfdrive.car.gm.values import DBC, CanBus, CarControllerParams
+from selfdrive.car.gm.values import DBC, CanBus, CarControllerParams, EV_CAR
VisualAlert = car.CarControl.HUDControl.VisualAlert
NetworkLocation = car.CarParams.NetworkLocation
@@ -79,8 +79,12 @@ class CarController:
self.apply_gas = self.params.MAX_ACC_REGEN
self.apply_brake = 0
else:
- self.apply_gas = int(round(interp(actuators.accel, self.params.GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V)))
- self.apply_brake = int(round(interp(actuators.accel, self.params.BRAKE_LOOKUP_BP, self.params.BRAKE_LOOKUP_V)))
+ if self.CP.carFingerprint in EV_CAR:
+ self.apply_gas = int(round(interp(actuators.accel, self.params.EV_GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V)))
+ self.apply_brake = int(round(interp(actuators.accel, self.params.EV_BRAKE_LOOKUP_BP, self.params.BRAKE_LOOKUP_V)))
+ else:
+ self.apply_gas = int(round(interp(actuators.accel, self.params.GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V)))
+ self.apply_brake = int(round(interp(actuators.accel, self.params.BRAKE_LOOKUP_BP, self.params.BRAKE_LOOKUP_V)))
idx = (self.frame // 4) % 4
diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py
index a81656e94c..8c136ceb68 100755
--- a/selfdrive/car/gm/interface.py
+++ b/selfdrive/car/gm/interface.py
@@ -140,6 +140,7 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 14.4 # end to end is 13.46
ret.centerToFront = ret.wheelbase * 0.4
ret.lateralTuning.pid.kf = 1. # get_steer_feedforward_acadia()
+ ret.longitudinalActuatorDelayUpperBound = 0.5 # large delay to initially start braking
elif candidate == CAR.BUICK_REGAL:
ret.mass = 3779. * CV.LB_TO_KG + STD_CARGO_KG # (3849+3708)/2
diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py
index 2667141aa3..7e784b6fd5 100644
--- a/selfdrive/car/gm/values.py
+++ b/selfdrive/car/gm/values.py
@@ -44,13 +44,17 @@ class CarControllerParams:
ACCEL_MAX = 2. # m/s^2
ACCEL_MIN = -4. # m/s^2
- GAS_LOOKUP_BP = [-1., 0., ACCEL_MAX]
+ EV_GAS_LOOKUP_BP = [-1., 0., ACCEL_MAX]
+ EV_BRAKE_LOOKUP_BP = [ACCEL_MIN, -1.]
+
+ # ICE has much less engine braking force compared to regen in EVs,
+ # lower threshold removes some braking deadzone
+ GAS_LOOKUP_BP = [-0.1, 0., ACCEL_MAX]
+ BRAKE_LOOKUP_BP = [ACCEL_MIN, -0.1]
+
GAS_LOOKUP_V = [MAX_ACC_REGEN, ZERO_GAS, MAX_GAS]
- BRAKE_LOOKUP_BP = [ACCEL_MIN, -1.]
BRAKE_LOOKUP_V = [MAX_BRAKE, 0.]
-STEER_THRESHOLD = 1.0
-
class CAR:
HOLDEN_ASTRA = "HOLDEN ASTRA RS-V BK 2017"
@@ -64,10 +68,13 @@ class CAR:
BOLT_EUV = "CHEVROLET BOLT EUV PREMIER 2022"
+EV_CAR = {CAR.VOLT}
+STEER_THRESHOLD = 1.0
+
+
class Footnote(Enum):
OBD_II = CarFootnote(
- 'Requires an OBD-II car harness and ' +
- 'community built ASCM harness. ' +
+ 'Requires a community built ASCM harness. ' +
'NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).',
Column.MODEL)
CAM_HARNESS = CarFootnote(
@@ -81,18 +88,18 @@ class Footnote(Enum):
@dataclass
class GMCarInfo(CarInfo):
package: str = "Adaptive Cruise Control"
- harness: Enum = Harness.none
+ harness: Enum = Harness.obd_ii
footnotes: List[Enum] = field(default_factory=lambda: [Footnote.OBD_II])
CAR_INFO: Dict[str, Union[GMCarInfo, List[GMCarInfo]]] = {
- CAR.HOLDEN_ASTRA: GMCarInfo("Holden Astra 2017", harness=Harness.custom),
- CAR.VOLT: GMCarInfo("Chevrolet Volt 2017-18", min_enable_speed=0, harness=Harness.custom),
+ CAR.HOLDEN_ASTRA: GMCarInfo("Holden Astra 2017"),
+ CAR.VOLT: GMCarInfo("Chevrolet Volt 2017-18", min_enable_speed=0),
CAR.CADILLAC_ATS: GMCarInfo("Cadillac ATS Premium Performance 2018"),
- CAR.MALIBU: GMCarInfo("Chevrolet Malibu Premier 2017", harness=Harness.custom),
+ CAR.MALIBU: GMCarInfo("Chevrolet Malibu Premier 2017"),
CAR.ACADIA: GMCarInfo("GMC Acadia 2018", video_link="https://www.youtube.com/watch?v=0ZN6DdsBUZo"),
CAR.BUICK_REGAL: GMCarInfo("Buick Regal Essence 2018"),
- CAR.ESCALADE_ESV: GMCarInfo("Cadillac Escalade ESV 2016", "Adaptive Cruise Control (ACC) & LKAS"), # TODO: can probably just be ACC?
+ CAR.ESCALADE_ESV: GMCarInfo("Cadillac Escalade ESV 2016", "Adaptive Cruise Control (ACC) & LKAS"),
CAR.SILVERADO: GMCarInfo("Chevrolet Silverado 1500 2020", "Driver Alert Package II", footnotes=[Footnote.CAM_HARNESS], harness=Harness.gm_cam),
CAR.BOLT_EUV: GMCarInfo("Chevrolet Bolt EUV Premier 2022", "Chevy Safety Assist", footnotes=[Footnote.CAM_HARNESS], harness=Harness.gm_cam),
}
diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py
index 88eaeaf76f..ec38123fa1 100644
--- a/selfdrive/car/hyundai/values.py
+++ b/selfdrive/car/hyundai/values.py
@@ -1,11 +1,10 @@
-from enum import Enum
from dataclasses import dataclass
from typing import Dict, List, Optional, Union
from cereal import car
from common.conversions import Conversions as CV
from selfdrive.car import dbc_dict
-from selfdrive.car.docs_definitions import CarFootnote, CarInfo, Column, Harness
+from selfdrive.car.docs_definitions import CarInfo, Harness
Ecu = car.CarParams.Ecu
@@ -88,12 +87,6 @@ class CAR:
GENESIS_G90 = "GENESIS G90 2017"
-class Footnote(Enum):
- CANFD = CarFootnote(
- "Requires a red panda and additional harness box.",
- Column.MODEL)
-
-
@dataclass
class HyundaiCarInfo(CarInfo):
# TODO: we can probably remove LKAS. LKAS is standard on many
@@ -141,7 +134,8 @@ CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = {
],
CAR.KIA_K5_2021: HyundaiCarInfo("Kia K5 2021-22", "Smart Cruise Control (SCC)", harness=Harness.hyundai_a),
CAR.KIA_NIRO_EV: [
- HyundaiCarInfo("Kia Niro Electric 2019-20", "All", video_link="https://www.youtube.com/watch?v=lT7zcG6ZpGo", harness=Harness.hyundai_f),
+ HyundaiCarInfo("Kia Niro Electric 2019", "All", video_link="https://www.youtube.com/watch?v=lT7zcG6ZpGo", harness=Harness.hyundai_h),
+ HyundaiCarInfo("Kia Niro Electric 2020", "All", video_link="https://www.youtube.com/watch?v=lT7zcG6ZpGo", harness=Harness.hyundai_f),
HyundaiCarInfo("Kia Niro Electric 2021", "All", video_link="https://www.youtube.com/watch?v=lT7zcG6ZpGo", harness=Harness.hyundai_c),
HyundaiCarInfo("Kia Niro Electric 2022", "All", video_link="https://www.youtube.com/watch?v=lT7zcG6ZpGo", harness=Harness.hyundai_h),
],
@@ -162,7 +156,7 @@ CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = {
],
CAR.KIA_STINGER: HyundaiCarInfo("Kia Stinger 2018-20", video_link="https://www.youtube.com/watch?v=MJ94qoofYw0", harness=Harness.hyundai_c),
CAR.KIA_CEED: HyundaiCarInfo("Kia Ceed 2019", harness=Harness.hyundai_e),
- CAR.KIA_EV6: HyundaiCarInfo("Kia EV6 2022", "All", harness=Harness.hyundai_p, footnotes=[Footnote.CANFD,]),
+ CAR.KIA_EV6: HyundaiCarInfo("Kia EV6 2022", "All", harness=Harness.hyundai_p),
# Genesis
CAR.GENESIS_G70: HyundaiCarInfo("Genesis G70 2018-19", "All", harness=Harness.hyundai_f),
@@ -742,6 +736,7 @@ FW_VERSIONS = {
b'\xf1\x00LX ESC \x0b 104 \x10\x16 58910-S8360',
b'\xf1\x00ON ESC \x0b 100\x18\x12\x18 58910-S9360',
b'\xf1\x00ON ESC \x0b 101\x19\t\x08 58910-S9360',
+ b'\xf1\x00ON ESC \x0b 101\x19\t\x05 58910-S9320',
],
(Ecu.engine, 0x7e0, None): [
b'\xf1\x81640J0051\x00\x00\x00\x00\x00\x00\x00\x00',
@@ -812,6 +807,7 @@ FW_VERSIONS = {
b'\xf1\x87LDMVBN899222KF37\xa8\x88x\x87\x97www\x98\x99\x99\x89\x88\x99\x98\x89f\x88\x96hdo\xf7\xff\xbb\xaa\x9f\xff\xe2U\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB5\xb9\x94\xe8\x89',
b"\xf1\x87LBLUFN622950KF36\xa8\x88\x88\x88\x87w\x87xh\x99\x96\x89\x88\x99\x98\x89\x88\x99\x98\x89\x87o\xf6\xff\x98\x88o\xffx'\xf1\x81U891\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U891\x00\x00\x00\x00\x00\x00SLX2G38NB3\xd1\xc3\xf8\xa8",
b'\xf1\x87LDMVBN950669KF37\x97www\x96fffy\x99\xa7\x99\xa9\x99\xaa\x99g\x88\x96x\xb8\x8f\xf9\xffTD/\xff\xa7\xcb\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB5\xb9\x94\xe8\x89',
+ b'\xf1\x87LDLVAA4478824HH1\x87wwwvfvg\x89\x99\xa8\x99w\x88\x87x\x89\x99\xa8\x99\xa6o\xfa\xfffU/\xffu\x92\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00TON4G38NB2[v\\\xb6',
],
},
CAR.VELOSTER: {
diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py
index 38a613b0e7..1e55e72ac4 100644
--- a/selfdrive/car/interfaces.py
+++ b/selfdrive/car/interfaces.py
@@ -61,6 +61,7 @@ class CarInterfaceBase(ABC):
self.steering_unpressed = 0
self.low_speed_alert = False
self.silent_steer_warning = True
+ self.v_ego_cluster_seen = False
self.CS = None
self.can_parsers = []
@@ -162,8 +163,10 @@ class CarInterfaceBase(ABC):
ret.canValid = all(cp.can_valid for cp in self.can_parsers if cp is not None)
ret.canTimeout = any(cp.bus_timeout for cp in self.can_parsers if cp is not None)
- if ret.vEgoCluster == 0.0:
+ if ret.vEgoCluster == 0.0 and not self.v_ego_cluster_seen:
ret.vEgoCluster = ret.vEgo
+ else:
+ self.v_ego_cluster_seen = True
if ret.cruiseState.speedCluster == 0:
ret.cruiseState.speedCluster = ret.cruiseState.speed
@@ -321,7 +324,7 @@ class CarStateBase(ABC):
def parse_gear_shifter(gear: Optional[str]) -> car.CarState.GearShifter:
if gear is None:
return GearShifter.unknown
-
+
d: Dict[str, car.CarState.GearShifter] = {
'P': GearShifter.park, 'PARK': GearShifter.park,
'R': GearShifter.reverse, 'REVERSE': GearShifter.reverse,
diff --git a/selfdrive/car/toyota/carcontroller.py b/selfdrive/car/toyota/carcontroller.py
index 858a3815b4..3326d7c96c 100644
--- a/selfdrive/car/toyota/carcontroller.py
+++ b/selfdrive/car/toyota/carcontroller.py
@@ -129,7 +129,7 @@ class CarController:
hud_control.rightLaneVisible, hud_control.leftLaneDepart,
hud_control.rightLaneDepart, CC.enabled))
- if self.frame % 100 == 0 and self.CP.enableDsu:
+ if (self.frame % 100 == 0 or send_ui) and self.CP.enableDsu:
can_sends.append(create_fcw_command(self.packer, fcw_alert))
# *** static msgs ***
diff --git a/selfdrive/manager/test/test_manager.py b/selfdrive/manager/test/test_manager.py
index a84ff264d2..f2e5319e8e 100755
--- a/selfdrive/manager/test/test_manager.py
+++ b/selfdrive/manager/test/test_manager.py
@@ -7,7 +7,7 @@ import unittest
import selfdrive.manager.manager as manager
from selfdrive.manager.process import DaemonProcess
from selfdrive.manager.process_config import managed_processes
-from system.hardware import AGNOS, HARDWARE
+from system.hardware import HARDWARE
os.environ['FAKEUPLOAD'] = "1"
@@ -35,8 +35,10 @@ class TestManager(unittest.TestCase):
t = time.monotonic() - start
assert t < MAX_STARTUP_TIME, f"startup took {t}s, expected <{MAX_STARTUP_TIME}s"
- # ensure all processes exit cleanly
def test_clean_exit(self):
+ """
+ Ensure all processes exit cleanly when stopped.
+ """
HARDWARE.set_power_save(False)
manager.manager_prepare()
for p in ALL_PROCESSES:
@@ -45,19 +47,18 @@ class TestManager(unittest.TestCase):
time.sleep(10)
for p in reversed(ALL_PROCESSES):
- state = managed_processes[p].get_process_state_msg()
- self.assertTrue(state.running, f"{p} not running")
+ with self.subTest(proc=p):
+ state = managed_processes[p].get_process_state_msg()
+ self.assertTrue(state.running, f"{p} not running")
+ exit_code = managed_processes[p].stop(retry=False)
- exit_code = managed_processes[p].stop(retry=False)
- if (AGNOS and p in ['ui',]):
- # TODO: make Qt UI exit gracefully
- continue
+ self.assertTrue(exit_code is not None, f"{p} failed to exit")
- # TODO: interrupted blocking read exits with 1 in cereal. use a more unique return code
- exit_codes = [0, 1]
- if managed_processes[p].sigkill:
- exit_codes = [-signal.SIGKILL]
- assert exit_code in exit_codes, f"{p} died with {exit_code}"
+ # TODO: interrupted blocking read exits with 1 in cereal. use a more unique return code
+ exit_codes = [0, 1]
+ if managed_processes[p].sigkill:
+ exit_codes = [-signal.SIGKILL]
+ self.assertIn(exit_code, exit_codes, f"{p} died with {exit_code}")
if __name__ == "__main__":
diff --git a/selfdrive/test/process_replay/model_replay_ref_commit b/selfdrive/test/process_replay/model_replay_ref_commit
index 9f9b822693..8b94834193 100644
--- a/selfdrive/test/process_replay/model_replay_ref_commit
+++ b/selfdrive/test/process_replay/model_replay_ref_commit
@@ -1 +1 @@
-df0ce74929dd6b5fa7a55224baefeff4bac6d785
+5c2cb8fb9787584a1eb553968cb87e7e6782dac5
diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit
index 0cf6711727..27bea55740 100644
--- a/selfdrive/test/process_replay/ref_commit
+++ b/selfdrive/test/process_replay/ref_commit
@@ -1 +1 @@
-82d3f0a3bfe07a76983e7e4603a0553d077ba15b
\ No newline at end of file
+c556add24a92c9d8593d9d3ebbeed9434b751d66
\ No newline at end of file
diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py
index 8007afb84c..31651706c6 100755
--- a/selfdrive/test/test_onroad.py
+++ b/selfdrive/test/test_onroad.py
@@ -5,7 +5,7 @@ import subprocess
import time
import numpy as np
import unittest
-from collections import Counter
+from collections import Counter, defaultdict
from pathlib import Path
from cereal import car
@@ -70,32 +70,40 @@ def cputime_total(ct):
return ct.cpuUser + ct.cpuSystem + ct.cpuChildrenUser + ct.cpuChildrenSystem
-def check_cpu_usage(first_proc, last_proc):
+def check_cpu_usage(proclogs):
result = "\n"
result += "------------------------------------------------\n"
result += "------------------ CPU Usage -------------------\n"
result += "------------------------------------------------\n"
+ plogs_by_proc = defaultdict(list)
+ for pl in proclogs:
+ for x in pl.procLog.procs:
+ if len(x.cmdline) > 0:
+ n = list(x.cmdline)[0]
+ plogs_by_proc[n].append(x)
+
+ print(plogs_by_proc.keys())
+
r = True
- dt = (last_proc.logMonoTime - first_proc.logMonoTime) / 1e9
- for proc_name, normal_cpu_usage in PROCS.items():
+ dt = (proclogs[-1].logMonoTime - proclogs[0].logMonoTime) / 1e9
+ for proc_name, expected_cpu in PROCS.items():
err = ""
- first, last = None, None
- try:
- first = [p for p in first_proc.procLog.procs if proc_name in p.cmdline][0]
- last = [p for p in last_proc.procLog.procs if proc_name in p.cmdline][0]
- cpu_time = cputime_total(last) - cputime_total(first)
+ cpu_usage = 0.
+ x = plogs_by_proc[proc_name]
+ if len(x) > 2:
+ cpu_time = cputime_total(x[-1]) - cputime_total(x[0])
cpu_usage = cpu_time / dt * 100.
- if cpu_usage > max(normal_cpu_usage * 1.15, normal_cpu_usage + 5.0):
+ if cpu_usage > max(expected_cpu * 1.15, expected_cpu + 5.0):
# cpu usage is high while playing sounds
if not (proc_name == "./_soundd" and cpu_usage < 65.):
err = "using more CPU than normal"
- elif cpu_usage < min(normal_cpu_usage * 0.65, max(normal_cpu_usage - 1.0, 0.0)):
+ elif cpu_usage < min(expected_cpu * 0.65, max(expected_cpu - 1.0, 0.0)):
err = "using less CPU than normal"
- except IndexError:
- err = f"NO METRICS FOUND {first=} {last=}\n"
+ else:
+ err = "NO METRICS FOUND"
- result += f"{proc_name.ljust(35)} {cpu_usage:5.2f}% ({normal_cpu_usage:5.2f}%) {err}\n"
+ result += f"{proc_name.ljust(35)} {cpu_usage:5.2f}% ({expected_cpu:5.2f}%) {err}\n"
if len(err) > 0:
r = False
@@ -111,6 +119,7 @@ class TestOnroad(unittest.TestCase):
if "DEBUG" in os.environ:
segs = filter(lambda x: os.path.exists(os.path.join(x, "rlog")), Path(ROOT).iterdir())
segs = sorted(segs, key=lambda x: x.stat().st_mtime)
+ print(segs[-1])
cls.lr = list(LogReader(os.path.join(segs[-1], "rlog")))
return
@@ -180,7 +189,7 @@ class TestOnroad(unittest.TestCase):
def test_cpu_usage(self):
proclogs = [m for m in self.lr if m.which() == 'procLog']
self.assertGreater(len(proclogs), service_list['procLog'].frequency * 45, "insufficient samples")
- cpu_ok = check_cpu_usage(proclogs[0], proclogs[-1])
+ cpu_ok = check_cpu_usage(proclogs)
self.assertTrue(cpu_ok)
def test_camera_processing_time(self):
diff --git a/selfdrive/ui/qt/maps/map.cc b/selfdrive/ui/qt/maps/map.cc
index 3967416f73..f81c3dd8f0 100644
--- a/selfdrive/ui/qt/maps/map.cc
+++ b/selfdrive/ui/qt/maps/map.cc
@@ -531,8 +531,7 @@ void MapInstructions::updateInstructions(cereal::NavInstruction::Reader instruct
}
auto icon = new QLabel;
- int wh = active ? 125 : 75;
- icon->setPixmap(loadPixmap(fn + ICON_SUFFIX, {wh, wh}, Qt::IgnoreAspectRatio));
+ icon->setPixmap(loadPixmap(fn + ICON_SUFFIX, {125, 125}, Qt::IgnoreAspectRatio));
icon->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
lane_layout->addWidget(icon);
}
diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc
index 0ab1424023..4414e602e6 100644
--- a/selfdrive/ui/qt/onroad.cc
+++ b/selfdrive/ui/qt/onroad.cc
@@ -193,7 +193,13 @@ void NvgWindow::updateState(const UIState &s) {
}
// Handle older routes where vEgoCluster is not set
- float v_ego = sm["carState"].getCarState().getVEgoCluster() == 0.0 ? sm["carState"].getCarState().getVEgo() : sm["carState"].getCarState().getVEgoCluster();
+ float v_ego;
+ if (sm["carState"].getCarState().getVEgoCluster() == 0.0 && !v_ego_cluster_seen) {
+ v_ego = sm["carState"].getCarState().getVEgo();
+ } else {
+ v_ego = sm["carState"].getCarState().getVEgoCluster();
+ v_ego_cluster_seen = true;
+ }
float cur_speed = cs_alive ? std::max(0.0, v_ego) : 0.0;
cur_speed *= s.scene.is_metric ? MS_TO_KPH : MS_TO_MPH;
diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h
index 7f51a73510..25920ccc6a 100644
--- a/selfdrive/ui/qt/onroad.h
+++ b/selfdrive/ui/qt/onroad.h
@@ -66,6 +66,7 @@ private:
bool rightHandDM = false;
bool has_us_speed_limit = false;
bool has_eu_speed_limit = false;
+ bool v_ego_cluster_seen = false;
int status = STATUS_DISENGAGED;
protected:
diff --git a/selfdrive/ui/qt/util.cc b/selfdrive/ui/qt/util.cc
index 381c065901..4be88aaf11 100644
--- a/selfdrive/ui/qt/util.cc
+++ b/selfdrive/ui/qt/util.cc
@@ -106,10 +106,19 @@ void setQtSurfaceFormat() {
QSurfaceFormat::setDefaultFormat(fmt);
}
+void sigTermHandler(int s) {
+ std::signal(s, SIG_DFL);
+ qApp->quit();
+}
+
void initApp(int argc, char *argv[]) {
Hardware::set_display_power(true);
Hardware::set_brightness(65);
+ // setup signal handlers to exit gracefully
+ std::signal(SIGINT, sigTermHandler);
+ std::signal(SIGTERM, sigTermHandler);
+
#ifdef __APPLE__
{
// Get the devicePixelRatio, and scale accordingly to maintain 1:1 rendering
diff --git a/selfdrive/ui/tests/test_translations.py b/selfdrive/ui/tests/test_translations.py
index ae91dd6f83..526dde93e8 100755
--- a/selfdrive/ui/tests/test_translations.py
+++ b/selfdrive/ui/tests/test_translations.py
@@ -32,9 +32,6 @@ class TestTranslations(unittest.TestCase):
def test_missing_translation_files(self):
for name, file in self.translation_files.items():
with self.subTest(name=name, file=file):
- if not len(file):
- self.skipTest(f"{name} translation has no defined file")
-
self.assertTrue(os.path.exists(os.path.join(TRANSLATIONS_DIR, f"{file}.ts")),
f"{name} has no XML translation file, run selfdrive/ui/update_translations.py")
@@ -43,9 +40,6 @@ class TestTranslations(unittest.TestCase):
for name, file in self.translation_files.items():
with self.subTest(name=name, file=file):
- if not len(file):
- self.skipTest(f"{name} translation has no defined file")
-
# caught by test_missing_translation_files
if not os.path.exists(os.path.join(TRANSLATIONS_DIR, f"{file}.ts")):
self.skipTest(f"{name} missing translation file")
@@ -59,13 +53,17 @@ class TestTranslations(unittest.TestCase):
def test_unfinished_translations(self):
for name, file in self.translation_files.items():
with self.subTest(name=name, file=file):
- if not len(file):
- raise self.skipTest(f"{name} translation has no defined file")
-
cur_translations = self._read_translation_file(TRANSLATIONS_DIR, file)
self.assertTrue(b"" not in cur_translations,
f"{file} ({name}) translation file has unfinished translations. Finish translations or mark them as completed in Qt Linguist")
+ def test_vanished_translations(self):
+ for name, file in self.translation_files.items():
+ with self.subTest(name=name, file=file):
+ cur_translations = self._read_translation_file(TRANSLATIONS_DIR, file)
+ self.assertTrue(b"" not in cur_translations,
+ f"{file} ({name}) translation file has obsolete translations. Run selfdrive/ui/update_translations.py --vanish to remove them")
+
if __name__ == "__main__":
unittest.main()
diff --git a/selfdrive/ui/translations/create_badges.py b/selfdrive/ui/translations/create_badges.py
index 58b587462f..d9e2d443b9 100755
--- a/selfdrive/ui/translations/create_badges.py
+++ b/selfdrive/ui/translations/create_badges.py
@@ -17,9 +17,6 @@ if __name__ == "__main__":
print("Copy into selfdrive/ui/translations/README.md:\n")
for name, file in translation_files.items():
- if not len(file):
- continue
-
with open(os.path.join(TRANSLATIONS_DIR, f"{file}.ts"), "r") as tr_f:
tr_file = tr_f.read()
diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts
index be0611f49a..20f96b8f40 100644
--- a/selfdrive/ui/translations/main_ja.ts
+++ b/selfdrive/ui/translations/main_ja.ts
@@ -340,27 +340,27 @@
MapETA
-
+
eta
予定到着時間
-
+
min
分
-
+
hr
時間
-
+
km
キロメートル
-
+
mi
マイル
@@ -490,30 +490,30 @@ location set
NvgWindow
-
+
km/h
km/h
-
+
mph
mph
-
-
+
+
MAX
最高速度
-
-
+
+
SPEED
速度
-
-
+
+
LIMIT
制限速度
diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts
index 626373a955..cd9c73c34d 100644
--- a/selfdrive/ui/translations/main_ko.ts
+++ b/selfdrive/ui/translations/main_ko.ts
@@ -340,27 +340,27 @@
MapETA
-
+
eta
도착
-
+
min
분
-
+
hr
시간
-
+
km
km
-
+
mi
mi
@@ -490,30 +490,30 @@ location set
NvgWindow
-
+
km/h
km/h
-
+
mph
mph
-
-
+
+
MAX
MAX
-
-
+
+
SPEED
SPEED
-
-
+
+
LIMIT
LIMIT
diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts
index 02bda87829..cb09e8c2ef 100644
--- a/selfdrive/ui/translations/main_zh-CHS.ts
+++ b/selfdrive/ui/translations/main_zh-CHS.ts
@@ -340,27 +340,27 @@
MapETA
-
+
eta
埃塔
-
+
min
分钟
-
+
hr
小时
-
+
km
km
-
+
mi
mi
@@ -488,30 +488,30 @@ location set
NvgWindow
-
+
km/h
km/h
-
+
mph
mph
-
-
+
+
MAX
最高定速
-
-
+
+
SPEED
SPEED
-
-
+
+
LIMIT
LIMIT
diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts
index 0ea8e95f52..58e921b313 100644
--- a/selfdrive/ui/translations/main_zh-CHT.ts
+++ b/selfdrive/ui/translations/main_zh-CHT.ts
@@ -340,27 +340,27 @@
MapETA
-
+
eta
抵達
-
+
min
分鐘
-
+
hr
小時
-
+
km
km
-
+
mi
mi
@@ -490,30 +490,30 @@ location set
NvgWindow
-
+
km/h
km/h
-
+
mph
mph
-
-
+
+
MAX
最高
-
-
+
+
SPEED
速度
-
-
+
+
LIMIT
速限
diff --git a/selfdrive/ui/update_translations.py b/selfdrive/ui/update_translations.py
index 78c973c86b..e509168ad6 100755
--- a/selfdrive/ui/update_translations.py
+++ b/selfdrive/ui/update_translations.py
@@ -17,11 +17,7 @@ def update_translations(vanish=False, plural_only=None, translations_dir=TRANSLA
with open(LANGUAGES_FILE, "r") as f:
translation_files = json.load(f)
- for name, file in translation_files.items():
- if not len(file):
- print(f"{name} has no translation file, skipping...")
- continue
-
+ for file in translation_files.values():
tr_file = os.path.join(translations_dir, f"{file}.ts")
args = f"lupdate -recursive {UI_DIR} -ts {tr_file}"
if vanish:
diff --git a/system/hardware/tici/test_power_draw.py b/system/hardware/tici/test_power_draw.py
index 4277bb9273..4b380372b9 100755
--- a/system/hardware/tici/test_power_draw.py
+++ b/system/hardware/tici/test_power_draw.py
@@ -37,6 +37,9 @@ class TestPowerDraw(unittest.TestCase):
HARDWARE.initialize_hardware()
HARDWARE.set_power_save(False)
+ # wait a bit for power save to disable
+ time.sleep(5)
+
def tearDown(self):
manager_cleanup()
diff --git a/tools/plotjuggler/juggle.py b/tools/plotjuggler/juggle.py
index 6f1038ec0d..08d75ccebe 100755
--- a/tools/plotjuggler/juggle.py
+++ b/tools/plotjuggler/juggle.py
@@ -23,6 +23,7 @@ DEMO_ROUTE = "4cf7a6ad03080c90|2021-09-29--13-46-36"
RELEASES_URL="https://github.com/commaai/PlotJuggler/releases/download/latest"
INSTALL_DIR = os.path.join(juggle_dir, "bin")
PLOTJUGGLER_BIN = os.path.join(juggle_dir, "bin/plotjuggler")
+MINIMUM_PLOTJUGGLER_VERSION = (3, 5, 2)
def install():
@@ -46,6 +47,12 @@ def install():
tar.extractall(path=INSTALL_DIR)
+def get_plotjuggler_version():
+ out = subprocess.check_output([PLOTJUGGLER_BIN, "-v"], encoding="utf-8").strip()
+ version = out.split(" ")[1]
+ return tuple(map(int, version.split(".")))
+
+
def load_segment(segment_name):
if segment_name is None:
return []
@@ -57,7 +64,7 @@ def load_segment(segment_name):
return []
-def start_juggler(fn=None, dbc=None, layout=None):
+def start_juggler(fn=None, dbc=None, layout=None, route_or_segment_name=None):
env = os.environ.copy()
env["BASEDIR"] = BASEDIR
env["PATH"] = f"{INSTALL_DIR}:{os.getenv('PATH', '')}"
@@ -69,6 +76,8 @@ def start_juggler(fn=None, dbc=None, layout=None):
extra_args += f" -d {fn}"
if layout is not None:
extra_args += f" -l {layout}"
+ if route_or_segment_name is not None:
+ extra_args += f" --window_title \"{route_or_segment_name}\""
cmd = f'{PLOTJUGGLER_BIN} --plugin_folders {INSTALL_DIR}{extra_args}'
subprocess.call(cmd, shell=True, env=env, cwd=juggle_dir)
@@ -129,7 +138,7 @@ def juggle_route(route_or_segment_name, segment_count, qlog, can, layout, dbc=No
with tempfile.NamedTemporaryFile(suffix='.rlog', dir=juggle_dir) as tmp:
save_log(tmp.name, all_data, compress=False)
del all_data
- start_juggler(tmp.name, dbc, layout)
+ start_juggler(tmp.name, dbc, layout, route_or_segment_name)
if __name__ == "__main__":
@@ -159,6 +168,10 @@ if __name__ == "__main__":
if not os.path.exists(PLOTJUGGLER_BIN):
print("PlotJuggler is missing. Downloading...")
install()
+
+ if get_plotjuggler_version() < MINIMUM_PLOTJUGGLER_VERSION:
+ ans = input("PlotJuggler is out of date. Installing update...")
+ install()
if args.stream:
start_juggler(layout=args.layout)
diff --git a/tools/replay/README.md b/tools/replay/README.md
index b705fb60db..2d0b702bd0 100644
--- a/tools/replay/README.md
+++ b/tools/replay/README.md
@@ -6,7 +6,7 @@
```bash
# Log in via browser to have access to non-public routes
-python lib/auth.py
+python tools/lib/auth.py
# Start a replay
tools/replay/replay
@@ -24,6 +24,7 @@ python replay/ui.py
```
## usage
+
``` bash
$ tools/replay/replay -h
Usage: tools/replay/replay [options] route
diff --git a/tools/sim/lib/replay.sh b/tools/sim/lib/replay.sh
deleted file mode 100755
index e65a4b69a7..0000000000
--- a/tools/sim/lib/replay.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-
-cd ~/openpilot/tools/nui
-
-# vision, boardd, sensorsd
-ALLOW=frame,can,ubloxRaw,health,sensorEvents,gpsNMEA,gpsLocationExternal ./nui "02ec6bea180a4d36/2019-10-25--10-18-09"