Merge branch 'SP-157-sync-20240614' into SP-157-sync-priv-20240614

This commit is contained in:
Jason Wen
2024-06-16 22:45:49 -04:00
71 changed files with 1930 additions and 1868 deletions
+2 -22
View File
@@ -69,11 +69,8 @@ jobs:
build:
strategy:
matrix:
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') && 'namespace-profile-arm64-2x8' || 'ubuntu-latest' }}
arch: ${{ fromJson('["x86_64"]') }} # TODO: Re-add build test for aarch64 once we switched to ubuntu-2404
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
@@ -90,23 +87,6 @@ jobs:
- uses: ./.github/workflows/compile-openpilot
timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 15 || 30) }} # allow more time when we missed the scons cache
docker_push_multiarch:
name: docker push multiarch tag
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot'
needs: [build]
steps:
- uses: actions/checkout@v4
with:
submodules: false
- name: Setup docker
run: |
$DOCKER_LOGIN
- name: Merge x64 and arm64 tags
run: |
export PUSH_IMAGE=true
scripts/retry.sh selfdrive/test/docker_tag_multiarch.sh base x86_64 aarch64
static_analysis:
name: static analysis
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
+19
View File
@@ -39,6 +39,25 @@ jobs:
source selfdrive/test/setup_vsound.sh && \
CI=1 pytest tools/sim/tests/test_metadrive_bridge.py"
test_python311:
name: test python3.11 support
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- name: Installing ubuntu dependencies
run: INSTALL_EXTRA_PACKAGES=no tools/install_ubuntu_dependencies.sh
- name: Installing python
uses: actions/setup-python@v5
with:
python-version: '3.11.4'
- name: Installing pip
run: pip install pip==24.0
- name: Installing poetry
run: pip install poetry==1.7.0
- name: Installing python dependencies
run: poetry install --no-cache --no-root
devcontainer:
name: devcontainer
runs-on: ubuntu-latest
+19
View File
@@ -84,3 +84,22 @@ build/
poetry.toml
Pipfile
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide
-1
View File
@@ -1 +0,0 @@
3.11.4
+4
View File
@@ -1,3 +1,7 @@
sunnypilot - 0.9.8.0 (2024-xx-xx)
========================
* Always on driver monitoring toggle
sunnypilot - 0.9.7.1 (2024-06-13)
========================
* New driving model
+3 -3
View File
@@ -64,11 +64,11 @@ RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER $USER
ENV POETRY_VIRTUALENVS_CREATE=false
ENV PYENV_VERSION=3.11.4
ENV PYENV_VERSION=3.12.4
ENV PYENV_ROOT="/home/$USER/pyenv"
ENV PATH="$PYENV_ROOT/bin:$PYENV_ROOT/shims:$PATH"
COPY --chown=$USER pyproject.toml poetry.lock .python-version /tmp/
COPY --chown=$USER pyproject.toml poetry.lock /tmp/
COPY --chown=$USER tools/install_python_dependencies.sh /tmp/tools/
RUN cd /tmp && \
@@ -76,7 +76,7 @@ RUN cd /tmp && \
rm -rf /tmp/* && \
rm -rf /home/$USER/.cache && \
find /home/$USER/pyenv -type d -name ".git" | xargs rm -rf && \
rm -rf /home/$USER/pyenv/versions/3.11.4/lib/python3.11/test
rm -rf /home/$USER/pyenv/versions/3.12.4/lib/python3.12/test
USER root
RUN sudo git config --global --add safe.directory /tmp/openpilot
+5 -3
View File
@@ -1,17 +1,19 @@
Version 0.9.8 (2024-XX-XX)
========================
* Always on driver monitoring toggle
* Added toggle to enable driver monitoring even when openpilot is not engaged
Version 0.9.7 (2024-06-11)
Version 0.9.7 (2024-06-13)
========================
* New driving model
* Inputs the past curvature for smoother and more accurate lateral control
* Simplified neural network architecture in the model's last layers
* Minor fixes to desire augmentation and weight decay
* New driver monitoring model
* Improved end-to-end bit for phone detection
* Adjust driving personality with the follow distance button
* Added toggle to enable driver monitoring even when openpilot is not engaged
* Support for hybrid variants of supported Ford models
* Fingerprinting without the OBD-II port on all cars
* Improved fuzzy fingerprinting for Ford and Volkswagen
Version 0.9.6 (2024-02-27)
========================
+3 -12
View File
@@ -1,11 +1,6 @@
# What is cereal? [![cereal tests](https://github.com/commaai/cereal/workflows/tests/badge.svg?event=push)](https://github.com/commaai/cereal/actions) [![codecov](https://codecov.io/gh/commaai/cereal/branch/master/graph/badge.svg)](https://codecov.io/gh/commaai/cereal)
# What is cereal?
cereal is both a messaging spec for robotics systems as well as generic high performance IPC pub sub messaging with a single publisher and multiple subscribers.
Imagine this use case:
* A sensor process reads gyro measurements directly from an IMU and publishes a `sensorEvents` packet
* A calibration process subscribes to the `sensorEvents` packet to use the IMU
* A localization process subscribes to the `sensorEvents` packet to use the IMU also
cereal is the messaging system for openpilot. It uses [msgq](https://github.com/commaai/msgq) as a pub/sub backend, and [Cap'n proto](https://capnproto.org/capnp-tool.html) for serialization of the structs.
## Messaging Spec
@@ -32,11 +27,7 @@ Forks of [openpilot](https://github.com/commaai/openpilot) might want to add thi
spec, however this could conflict with future changes made in mainline cereal/openpilot. Rebasing against mainline openpilot
then means breaking backwards-compatibility with all old logs of your fork. So we added reserved events in
[custom.capnp](custom.capnp) that we will leave empty in mainline cereal/openpilot. **If you only modify those, you can ensure your
fork will remain backwards-compatible with all versions of mainline cereal/openpilot and your fork.**
## Pub Sub Backends
cereal supports two backends, one based on [zmq](https://zeromq.org/) and another called [msgq](messaging/msgq.cc), a custom pub sub based on shared memory that doesn't require the bytes to pass through the kernel.
fork will remain backwards-compatible with all versions of mainline openpilot and your fork.**
Example
---
+4 -4
View File
@@ -539,8 +539,7 @@ struct CarParams {
startingState @70 :Bool; # Does this car make use of special starting state
steerActuatorDelay @36 :Float32; # Steering wheel actuator delay in seconds
longitudinalActuatorDelayLowerBound @61 :Float32; # Gas/Brake actuator delay in seconds, lower bound
longitudinalActuatorDelayUpperBound @58 :Float32; # Gas/Brake actuator delay in seconds, upper bound
longitudinalActuatorDelay @58 :Float32; # Gas/Brake actuator delay in seconds
openpilotLongitudinalControl @37 :Bool; # is openpilot doing the longitudinal control?
carVin @38 :Text; # VIN number queried during fingerprinting
dashcamOnly @41: Bool;
@@ -593,8 +592,8 @@ struct CarParams {
kiBP @2 :List(Float32);
kiV @3 :List(Float32);
kf @6 :Float32;
deadzoneBP @4 :List(Float32);
deadzoneV @5 :List(Float32);
deadzoneBPDEPRECATED @4 :List(Float32);
deadzoneVDEPRECATED @5 :List(Float32);
}
struct LateralINDITuning {
@@ -754,4 +753,5 @@ struct CarParams {
brakeMaxVDEPRECATED @16 :List(Float32);
directAccelControlDEPRECATED @30 :Bool;
maxSteeringAngleDegDEPRECATED @54 :Float32;
longitudinalActuatorDelayLowerBoundDEPRECATEDDEPRECATED @61 :Float32;
}
+7 -3
View File
@@ -698,7 +698,6 @@ struct ControlsState @0x97ff69c53601abf1 {
personality @66 :LongitudinalPersonality;
longControlState @30 :Car.CarControl.Actuators.LongControlState;
vPid @2 :Float32;
vTargetLead @3 :Float32;
vCruise @22 :Float32; # actual set speed
vCruiseCluster @63 :Float32; # set speed to display in the UI
@@ -866,6 +865,7 @@ struct ControlsState @0x97ff69c53601abf1 {
canMonoTimesDEPRECATED @21 :List(UInt64);
desiredCurvatureRateDEPRECATED @62 :Float32;
canErrorCounterDEPRECATED @57 :UInt32;
vPidDEPRECATED @2 :Float32;
}
# All SI units and in device frame
@@ -1060,6 +1060,11 @@ struct LongitudinalPlan @0xe00b5b3eba12876c {
accels @32 :List(Float32);
speeds @33 :List(Float32);
jerks @34 :List(Float32);
aTarget @18 :Float32;
shouldStop @37: Bool;
allowThrottle @38: Bool;
allowBrake @39: Bool;
solverExecutionTime @35 :Float32;
@@ -1076,7 +1081,6 @@ struct LongitudinalPlan @0xe00b5b3eba12876c {
aCruiseDEPRECATED @17 :Float32;
vTargetDEPRECATED @3 :Float32;
vTargetFutureDEPRECATED @14 :Float32;
aTargetDEPRECATED @18 :Float32;
vStartDEPRECATED @26 :Float32;
aStartDEPRECATED @27 :Float32;
vMaxDEPRECATED @20 :Float32;
@@ -2244,7 +2248,6 @@ struct Event {
carControl @23 :Car.CarControl;
carOutput @127 :Car.CarOutput;
longitudinalPlan @24 :LongitudinalPlan;
uiPlan @106 :UiPlan;
ubloxGnss @34 :UbloxGnss;
ubloxRaw @39 :Data;
qcomGnss @31 :QcomGnss;
@@ -2365,5 +2368,6 @@ struct Event {
sensorEventsDEPRECATED @11 :List(SensorEventData);
lateralPlanDEPRECATED @64 :LateralPlan;
navModelDEPRECATED @104 :NavModelData;
uiPlanDEPRECATED @106 :UiPlan;
}
}
+1 -1
View File
@@ -69,7 +69,7 @@ _services: dict[str, tuple] = {
"navThumbnail": (True, 0.),
"navModelDEPRECATED": (True, 2., 4.),
"mapRenderState": (True, 2., 1.),
"uiPlan": (True, 20., 40.),
"uiPlanDEPRECATED": (True, 20., 40.),
"qRoadEncodeIdx": (False, 20.),
"userFlag": (True, 0., 1),
"microphone": (True, 10., 10),
+2 -2
View File
@@ -1,7 +1,7 @@
import jwt
import requests
import unicodedata
from datetime import datetime, timedelta
from datetime import datetime, timedelta, UTC
from openpilot.system.hardware.hw import Paths
from openpilot.system.version import get_version
@@ -24,7 +24,7 @@ class BaseApi:
return self.api_get(endpoint, method=method, timeout=timeout, access_token=access_token, **params)
def _get_token(self, expiry_hours=1, **extra_payload):
now = datetime.utcnow()
now = datetime.now(UTC).replace(tzinfo=None)
payload = {
'identity': self.dongle_id,
'nbf': now,
+3 -3
View File
@@ -6,7 +6,7 @@ import threading
import psutil
from collections import deque
from setproctitle import getproctitle
from openpilot.common.threadname import getthreadname
from openpilot.system.hardware import PC
@@ -62,7 +62,7 @@ class Ratekeeper:
self._print_delay_threshold = print_delay_threshold
self._frame = 0
self._remaining = 0.0
self._process_name = getproctitle()
self._thread_name = getthreadname()
self._dts = deque([self._interval], maxlen=100)
self._last_monitor_time = time.monotonic()
@@ -97,7 +97,7 @@ class Ratekeeper:
remaining = self._next_frame_time - time.monotonic()
self._next_frame_time += self._interval
if self._print_delay_threshold is not None and remaining < -self._print_delay_threshold:
print(f"{self._process_name} lagging by {-remaining * 1000:.2f} ms")
print(f"{self._thread_name} lagging by {-remaining * 1000:.2f} ms")
lagged = True
self._frame += 1
self._remaining = remaining
+8
View File
@@ -0,0 +1,8 @@
from openpilot.common.threadname import setthreadname, getthreadname, LINUX
class TestThreadName:
def test_set_get_threadname(self):
if LINUX:
name = 'TESTING'
setthreadname(name)
assert name == getthreadname()
+19
View File
@@ -0,0 +1,19 @@
import ctypes
import os
LINUX = os.name == 'posix' and os.uname().sysname == 'Linux'
if LINUX:
libc = ctypes.CDLL('libc.so.6')
def setthreadname(name: str) -> None:
if LINUX:
name = name[-15:] + '\0'
libc.prctl(15, str.encode(name), 0, 0, 0)
def getthreadname() -> str:
if LINUX:
name = ctypes.create_string_buffer(16)
libc.prctl(16, name)
return name.value.decode('utf-8')
return ""
+1 -1
View File
@@ -1 +1 @@
#define COMMA_VERSION "0.9.7.1"
#define COMMA_VERSION "0.9.8.0"
+4 -4
View File
@@ -90,9 +90,9 @@ A supported vehicle is one that just works when you install a comma device. All
|Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra Hybrid 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai J connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Genesis 2015-16">Buy Here</a></sub></details>||
|Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=i30 2017-19">Buy Here</a></sub></details>||
|Hyundai|Ioniq 5 (Southeast Asia only) 2022-23[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq 5 (Southeast Asia only) 2022-23">Buy Here</a></sub></details>||
|Hyundai|Ioniq 5 (with HDA II) 2022-23[<sup>5</sup>](#footnotes)|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq 5 (with HDA II) 2022-23">Buy Here</a></sub></details>||
|Hyundai|Ioniq 5 (without HDA II) 2022-23[<sup>5</sup>](#footnotes)|Highway Driving Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq 5 (without HDA II) 2022-23">Buy Here</a></sub></details>||
|Hyundai|Ioniq 5 (Non-US only) 2022-24[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq 5 (Non-US only) 2022-24">Buy Here</a></sub></details>||
|Hyundai|Ioniq 5 (with HDA II) 2022-24[<sup>5</sup>](#footnotes)|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq 5 (with HDA II) 2022-24">Buy Here</a></sub></details>||
|Hyundai|Ioniq 5 (without HDA II) 2022-24[<sup>5</sup>](#footnotes)|Highway Driving Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq 5 (without HDA II) 2022-24">Buy Here</a></sub></details>||
|Hyundai|Ioniq 6 (with HDA II) 2023-24[<sup>5</sup>](#footnotes)|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq 6 (with HDA II) 2023-24">Buy Here</a></sub></details>||
|Hyundai|Ioniq Electric 2019|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq Electric 2019">Buy Here</a></sub></details>||
|Hyundai|Ioniq Electric 2020|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq Electric 2020">Buy Here</a></sub></details>||
@@ -127,7 +127,7 @@ A supported vehicle is one that just works when you install a comma device. All
|Kia|Carnival 2022-24[<sup>5</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Carnival 2022-24">Buy Here</a></sub></details>||
|Kia|Carnival (China only) 2023[<sup>5</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Carnival (China only) 2023">Buy Here</a></sub></details>||
|Kia|Ceed 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Ceed 2019">Buy Here</a></sub></details>||
|Kia|EV6 (Southeast Asia only) 2022-24[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=EV6 (Southeast Asia only) 2022-24">Buy Here</a></sub></details>||
|Kia|EV6 (Non-US only) 2022-24[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=EV6 (Non-US only) 2022-24">Buy Here</a></sub></details>||
|Kia|EV6 (with HDA II) 2022-24[<sup>5</sup>](#footnotes)|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=EV6 (with HDA II) 2022-24">Buy Here</a></sub></details>||
|Kia|EV6 (without HDA II) 2022-24[<sup>5</sup>](#footnotes)|Highway Driving Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=EV6 (without HDA II) 2022-24">Buy Here</a></sub></details>||
|Kia|Forte 2019-21|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|6 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Forte 2019-21">Buy Here</a></sub></details>||
Generated
+1526 -1482
View File
File diff suppressed because one or more lines are too long
+38 -34
View File
@@ -88,7 +88,7 @@ repository = "https://github.com/commaai/openpilot"
documentation = "https://docs.comma.ai"
[tool.poetry.dependencies]
python = "~3.11"
python = ">=3.11, <3.13"
# multiple users
sounddevice = "*" # micd + soundd
@@ -137,40 +137,22 @@ future-fstrings = "*"
# these should be removed
psutil = "*"
timezonefinder = "*" # just used for nav ETA
setproctitle = "*"
pycryptodome = "*" # used in updated/casync, panda, body, and a test
[tool.poetry.group.dev.dependencies]
av = "*"
azure-identity = "*"
azure-storage-blob = "*"
breathe = "*"
control = "*"
coverage = "*"
dictdiffer = "*"
flaky = "*"
hypothesis = "~6.47"
inputs = "*"
#logreader
zstd = "*"
[tool.poetry.group.docs.dependencies]
Jinja2 = "*"
lru-dict = "*"
matplotlib = "*"
# No release for this fix https://github.com/metadriverse/metadrive/issues/632. Pinned to this commit until next release
metadrive-simulator = {git = "https://github.com/metadriverse/metadrive.git", rev ="233a3a1698be7038ec3dd050ca10b547b4b3324c", markers = "platform_machine != 'aarch64'" } # no linux/aarch64 wheels for certain dependencies
mpld3 = "*"
sphinx = "*"
sphinx-rtd-theme = "*"
sphinx-sitemap = "*"
[tool.poetry.group.testing.dependencies]
coverage = "*"
hypothesis = "~6.47"
mypy = "*"
myst-parser = "*"
natsort = "*"
opencv-python-headless = "*"
parameterized = "^0.8"
pprofile = "*"
polyline = "*"
pre-commit = "*"
pyautogui = "*"
pytools = "<=2024.1.3" # our pinned version of pyopencl use a broken version of pytools
pyopencl = "==2023.1.4" # 2024.1 is broken on arm64
pygame = "*"
pywinctl = "*"
pyprof2calltree = "*"
pytest = "*"
pytest-cov = "*"
pytest-cpp = "*"
@@ -181,11 +163,33 @@ pytest-randomly = "*"
pytest-asyncio = "*"
pytest-mock = "*"
pytest-repeat = "*"
rerun-sdk = "*"
ruff = "*"
sphinx = "*"
sphinx-rtd-theme = "*"
sphinx-sitemap = "*"
[tool.poetry.group.dev.dependencies]
av = "*"
azure-identity = "*"
azure-storage-blob = "*"
breathe = "*"
control = "*"
dictdiffer = "*"
flaky = "*"
inputs = "*"
lru-dict = "*"
matplotlib = "*"
metadrive-simulator = { git = "https://github.com/commaai/metadrive.git", branch = "python3.12", markers = "platform_machine != 'aarch64'" } # no linux/aarch64 wheels for certain dependencies
mpld3 = "*"
myst-parser = "*"
natsort = "*"
opencv-python-headless = "*"
parameterized = "^0.8"
#pprofile = "*"
polyline = "*"
pyautogui = "*"
pygame = "*"
pyopencl = { version = "*", markers = "platform_machine != 'aarch64'" } # broken on arm64
pywinctl = "*"
pyprof2calltree = "*"
rerun-sdk = "*"
tabulate = "*"
types-requests = "*"
types-tabulate = "*"
+36
View File
@@ -0,0 +1,36 @@
# openpilot releases
## release checklist
**Go to `devel-staging`**
- [ ] update `devel-staging`: `git reset --hard origin/master-ci`
- [ ] open a pull request from `devel-staging` to `devel`
**Go to `devel`**
- [ ] update RELEASES.md
- [ ] close out milestone
- [ ] post on Discord dev channel
- [ ] bump version on master: `common/version.h` and `RELEASES.md`
- [ ] merge the pull request
tests:
- [ ] update from previous release -> new release
- [ ] update from new release -> previous release
- [ ] fresh install with `openpilot-test.comma.ai`
- [ ] drive on fresh install
- [ ] comma body test
- [ ] no submodules or LFS
- [ ] check sentry, MTBF, etc.
**Go to `release3`**
- [ ] publish the blog post
- [ ] `git reset --hard origin/release3-staging`
- [ ] tag the release
```
git tag v0.X.X <commit-hash>
git push origin v0.X.X
```
- [ ] create GitHub release
- [ ] final test install on `openpilot.comma.ai`
- [ ] update production
- [ ] Post on Discord, X, etc.
+8 -2
View File
@@ -33,16 +33,22 @@ blacklist = [
"matlab.*.md",
".git$", # for submodules
".git/",
".github/",
".devcontainer/",
"Darwin/",
".vscode/",
# no LFS
# common things
"LICENSE",
"Dockerfile",
".pre-commit",
# no LFS or submodules in release
".lfsconfig",
".gitattributes",
".git$",
".gitmodules",
]
# Sunnypilot blacklist
+2 -2
View File
@@ -3,7 +3,7 @@ import os
import time
import numpy as np
from multiprocessing import Process
from setproctitle import setproctitle
from openpilot.common.threadname import setthreadname
def waste(core):
os.sched_setaffinity(0, [core,])
@@ -16,7 +16,7 @@ def waste(core):
j = 0
while 1:
if (i % 100) == 0:
setproctitle("%3d: %8d" % (core, i))
setthreadname("%3d: %8d" % (core, i))
lt = time.monotonic()
print("%3d: %8d %f %.2f" % (core, i, lt-st, j))
st = lt
+13 -3
View File
@@ -71,25 +71,35 @@ def get_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, que
if __name__ == "__main__":
import argparse
from openpilot.common.params import Params
from openpilot.selfdrive.car.fw_versions import set_obd_multiplexing
parser = argparse.ArgumentParser(description='Get addresses of all ECUs')
parser.add_argument('--debug', action='store_true')
parser.add_argument('--bus', type=int, default=1)
parser.add_argument('--no-obd', action='store_true')
parser.add_argument('--timeout', type=float, default=1.0)
args = parser.parse_args()
logcan = messaging.sub_sock('can')
sendcan = messaging.pub_sock('sendcan')
time.sleep(1.0)
# Set up params for pandad
params = Params()
params.remove("FirmwareQueryDone")
params.put_bool("IsOnroad", False)
time.sleep(0.2) # thread is 10 Hz
params.put_bool("IsOnroad", True)
set_obd_multiplexing(params, not args.no_obd)
print("Getting ECU addresses ...")
ecu_addrs = get_all_ecu_addrs(logcan, sendcan, args.bus, args.timeout, debug=args.debug)
print()
print("Found ECUs on addresses:")
print("Found ECUs on rx addresses:")
for addr, subaddr, _ in ecu_addrs:
msg = f" 0x{hex(addr)}"
msg = f" {hex(addr)}"
if subaddr is not None:
msg += f" (sub-address: {hex(subaddr)})"
print(msg)
-4
View File
@@ -27,10 +27,6 @@ class CarInterface(CarInterfaceBase):
ret.steerActuatorDelay = 0.2
ret.steerLimitTimer = 1.0
ret.longitudinalTuning.kpBP = [0.]
ret.longitudinalTuning.kpV = [0.5]
ret.longitudinalTuning.kiV = [0.]
CAN = CanBus(fingerprint=fingerprint)
cfgs = [get_safety_config(car.CarParams.SafetyModel.ford)]
if CAN.main >= 4:
+4 -10
View File
@@ -94,11 +94,7 @@ class CarInterface(CarInterfaceBase):
else:
ret.transmissionType = TransmissionType.automatic
ret.longitudinalTuning.deadzoneBP = [0.]
ret.longitudinalTuning.deadzoneV = [0.15]
ret.longitudinalTuning.kpBP = [5., 35.]
ret.longitudinalTuning.kiBP = [0.]
ret.longitudinalTuning.kiBP = [5., 35.]
if candidate in CAMERA_ACC_CAR:
ret.experimentalLongitudinalAvailable = True
@@ -110,8 +106,7 @@ class CarInterface(CarInterfaceBase):
ret.minSteerSpeed = 10 * CV.KPH_TO_MS
# Tuning for experimental long
ret.longitudinalTuning.kpV = [2.0, 1.5]
ret.longitudinalTuning.kiV = [0.72]
ret.longitudinalTuning.kiV = [2.0, 1.5]
ret.stoppingDecelRate = 2.0 # reach brake quickly after enabling
ret.vEgoStopping = 0.25
ret.vEgoStarting = 0.25
@@ -131,8 +126,7 @@ class CarInterface(CarInterfaceBase):
ret.minSteerSpeed = 7 * CV.MPH_TO_MS
# Tuning
ret.longitudinalTuning.kpV = [2.4, 1.5]
ret.longitudinalTuning.kiV = [0.36]
ret.longitudinalTuning.kiV = [2.4, 1.5]
# These cars have been put into dashcam only due to both a lack of users and test coverage.
# These cars likely still work fine. Once a user confirms each car works and a test route is
@@ -148,7 +142,7 @@ class CarInterface(CarInterfaceBase):
ret.steerLimitTimer = 0.4
ret.radarTimeStep = 0.0667 # GM radar runs at 15Hz instead of standard 20Hz
ret.longitudinalActuatorDelayUpperBound = 0.5 # large delay to initially start braking
ret.longitudinalActuatorDelay = 0.5 # large delay to initially start braking
if candidate == CAR.CHEVROLET_VOLT:
ret.lateralTuning.pid.kpBP = [0., 40.]
+3 -7
View File
@@ -77,17 +77,13 @@ class CarInterface(CarInterfaceBase):
ret.lateralTuning.pid.kf = 0.00006 # conservative feed-forward
if candidate in HONDA_BOSCH:
ret.longitudinalTuning.kpV = [0.25]
ret.longitudinalTuning.kiV = [0.05]
ret.longitudinalActuatorDelayUpperBound = 0.5 # s
ret.longitudinalActuatorDelay = 0.5 # s
if candidate in HONDA_BOSCH_RADARLESS:
ret.stopAccel = CarControllerParams.BOSCH_ACCEL_MIN # stock uses -4.0 m/s^2 once stopped but limited by safety model
else:
# default longitudinal tuning for all hondas
ret.longitudinalTuning.kpBP = [0., 5., 35.]
ret.longitudinalTuning.kpV = [1.2, 0.8, 0.5]
ret.longitudinalTuning.kiBP = [0., 35.]
ret.longitudinalTuning.kiV = [0.18, 0.12]
ret.longitudinalTuning.kiBP = [0., 5., 35.]
ret.longitudinalTuning.kiV = [1.2, 0.8, 0.5]
eps_modified = False
for fw in car_fw:
+5
View File
@@ -2,6 +2,9 @@
from cereal import car
from openpilot.selfdrive.car.hyundai.values import CAR
# The existence of SCC or RDR in the fwdRadar FW usually determines the radar's function,
# i.e. if it sends the SCC messages or if another ECU like the camera or ADAS Driving ECU does
Ecu = car.CarParams.Ecu
FINGERPRINTS = {
@@ -995,6 +998,8 @@ FW_VERSIONS = {
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.03 99211-GI010 220401',
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.05 99211-GI010 220614',
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.06 99211-GI010 230110',
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.00 99211-GI100 230915',
b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.00 99211-GI100 230915',
],
},
CAR.HYUNDAI_IONIQ_6: {
+1 -6
View File
@@ -91,14 +91,10 @@ class CarInterface(CarInterfaceBase):
# *** longitudinal control ***
if candidate in CANFD_CAR:
ret.longitudinalTuning.kpV = [0.1]
ret.longitudinalTuning.kiV = [0.0]
ret.experimentalLongitudinalAvailable = candidate not in (CANFD_UNSUPPORTED_LONGITUDINAL_CAR | CANFD_RADAR_SCC_CAR | NON_SCC_CAR)
if ret.flags & HyundaiFlags.CANFD_CAMERA_SCC and not hda2:
ret.spFlags |= HyundaiFlagsSP.SP_CAMERA_SCC_LEAD.value
else:
ret.longitudinalTuning.kpV = [0.5]
ret.longitudinalTuning.kiV = [0.0]
ret.experimentalLongitudinalAvailable = candidate not in (UNSUPPORTED_LONGITUDINAL_CAR | NON_SCC_CAR)
if candidate in CAMERA_SCC_CAR:
ret.spFlags |= HyundaiFlagsSP.SP_CAMERA_SCC_LEAD.value
@@ -109,8 +105,7 @@ class CarInterface(CarInterfaceBase):
ret.startingState = True
ret.vEgoStarting = 0.1
ret.startAccel = 1.0
ret.longitudinalActuatorDelayLowerBound = 0.5
ret.longitudinalActuatorDelayUpperBound = 0.5
ret.longitudinalActuatorDelay = 0.5
if DBC[ret.carFingerprint]["radar"] is None:
if ret.spFlags & (HyundaiFlagsSP.SP_ENHANCED_SCC | HyundaiFlagsSP.SP_CAMERA_SCC_LEAD):
+4 -4
View File
@@ -320,9 +320,9 @@ class CAR(Platforms):
)
HYUNDAI_IONIQ_5 = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Hyundai Ioniq 5 (Southeast Asia only) 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_q])),
HyundaiCarDocs("Hyundai Ioniq 5 (without HDA II) 2022-23", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_k])),
HyundaiCarDocs("Hyundai Ioniq 5 (with HDA II) 2022-23", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_q])),
HyundaiCarDocs("Hyundai Ioniq 5 (Non-US only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_q])),
HyundaiCarDocs("Hyundai Ioniq 5 (without HDA II) 2022-24", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_k])),
HyundaiCarDocs("Hyundai Ioniq 5 (with HDA II) 2022-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_q])),
],
CarSpecs(mass=1948, wheelbase=2.97, steerRatio=14.26, tireStiffnessFactor=0.65),
flags=HyundaiFlags.EV,
@@ -492,7 +492,7 @@ class CAR(Platforms):
)
KIA_EV6 = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Kia EV6 (Southeast Asia only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_p])),
HyundaiCarDocs("Kia EV6 (Non-US only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_p])),
HyundaiCarDocs("Kia EV6 (without HDA II) 2022-24", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_l])),
HyundaiCarDocs("Kia EV6 (with HDA II) 2022-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_p]))
],
+3 -6
View File
@@ -379,16 +379,13 @@ class CarInterfaceBase(ABC):
ret.vEgoStopping = 0.5
ret.vEgoStarting = 0.5
ret.stoppingControl = True
ret.longitudinalTuning.deadzoneBP = [0.]
ret.longitudinalTuning.deadzoneV = [0.]
ret.longitudinalTuning.kf = 1.
ret.longitudinalTuning.kpBP = [0.]
ret.longitudinalTuning.kpV = [1.]
ret.longitudinalTuning.kpV = [0.]
ret.longitudinalTuning.kiBP = [0.]
ret.longitudinalTuning.kiV = [1.]
ret.longitudinalTuning.kiV = [0.]
# TODO estimate car specific lag, use .15s for now
ret.longitudinalActuatorDelayLowerBound = 0.15
ret.longitudinalActuatorDelayUpperBound = 0.15
ret.longitudinalActuatorDelay = 0.15
ret.steerLimitTimer = 1.0
return ret
-5
View File
@@ -107,11 +107,6 @@ class CarInterface(CarInterfaceBase):
ret.flags |= SubaruFlags.DISABLE_EYESIGHT.value
if ret.openpilotLongitudinalControl:
ret.longitudinalTuning.kpBP = [0., 5., 35.]
ret.longitudinalTuning.kpV = [0.8, 1.0, 1.5]
ret.longitudinalTuning.kiBP = [0., 35.]
ret.longitudinalTuning.kiV = [0.54, 0.36]
ret.stoppingControl = True
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_SUBARU_LONG
+1 -6
View File
@@ -18,12 +18,7 @@ class CarInterface(CarInterfaceBase):
ret.steerControlType = car.CarParams.SteerControlType.angle
# Set kP and kI to 0 over the whole speed range to have the planner accel as actuator command
ret.longitudinalTuning.kpBP = [0]
ret.longitudinalTuning.kpV = [0]
ret.longitudinalTuning.kiBP = [0]
ret.longitudinalTuning.kiV = [0]
ret.longitudinalActuatorDelayUpperBound = 0.5 # s
ret.longitudinalActuatorDelay = 0.5 # s
ret.radarTimeStep = (1.0 / 8) # 8Hz
# Check if we have messages on an auxiliary panda, and that 0x2bf (DAS_control) is present on the AP powertrain bus
@@ -75,7 +75,6 @@ class TestCarInterfaces:
# Longitudinal sanity checks
assert len(car_params.longitudinalTuning.kpV) == len(car_params.longitudinalTuning.kpBP)
assert len(car_params.longitudinalTuning.kiV) == len(car_params.longitudinalTuning.kiBP)
assert len(car_params.longitudinalTuning.deadzoneV) == len(car_params.longitudinalTuning.deadzoneBP)
# If we're using the interceptor for gasPressed, we should be commanding gas with it
if car_params.enableGasInterceptorDEPRECATED:
+13 -14
View File
@@ -161,23 +161,22 @@ class CarInterface(CarInterfaceBase):
sp_tss2_long_tune = Params().get_bool("ToyotaTSS2Long")
tune = ret.longitudinalTuning
tune.deadzoneBP = [0., 9.]
tune.deadzoneV = [.0, .15]
if candidate in TSS2_CAR or ret.enableGasInterceptorDEPRECATED:
tune.kpBP = [0., 5., 20., 30.] if sp_tss2_long_tune else [0., 5., 20.]
tune.kpV = [1.3, 1.0, 0.7, 0.1] if sp_tss2_long_tune else [1.3, 1.0, 0.7]
tune.kiBP = [0., 1., 2., 3., 4., 5., 12., 20., 27., 40.] if sp_tss2_long_tune else [0., 5., 12., 20., 27.]
tune.kiV = [.348, .3361, .3168, .2831, .2571, .226, .198, .17, .10, .01] if sp_tss2_long_tune else [.35, .23, .20, .17, .1]
if sp_tss2_long_tune:
tune.kpBP = [0., 5., 20., 30.]
tune.kpV = [1.3, 1.0, 0.7, 0.1]
tune.kiBP = [0., 1., 2., 3., 4., 5., 12., 20., 27., 40.]
tune.kiV = [.348, .3361, .3168, .2831, .2571, .226, .198, .17, .10, .01]
else:
tune.kpV = [0.0]
tune.kiV = [0.5]
if candidate in TSS2_CAR:
ret.vEgoStopping = 0.15 if sp_tss2_long_tune else 0.25
ret.vEgoStarting = 0.15 if sp_tss2_long_tune else 0.25
ret.stopAccel = -0.4 if sp_tss2_long_tune else 0
ret.stoppingDecelRate = 0.05 if sp_tss2_long_tune else 0.3 # reach stopping target smoothly
ret.vEgoStopping = 0.25
ret.vEgoStarting = 0.25
ret.stoppingDecelRate = 0.3 # reach stopping target smoothly
else:
tune.kpBP = [0., 5., 35.]
tune.kiBP = [0., 35.]
tune.kpV = [3.6, 2.4, 1.5]
tune.kiV = [0.54, 0.36]
tune.kiBP = [0., 5., 35.]
tune.kiV = [3.6, 2.4, 1.5]
return ret
-2
View File
@@ -108,8 +108,6 @@ class CarInterface(CarInterfaceBase):
ret.stopAccel = -0.55
ret.vEgoStarting = 0.1
ret.vEgoStopping = 0.5
ret.longitudinalTuning.kpV = [0.1]
ret.longitudinalTuning.kiV = [0.0]
ret.autoResumeSng = ret.minEnableSpeed == -1
return ret
+3 -5
View File
@@ -634,13 +634,12 @@ class Controls:
if not CC.latActive:
self.LaC.reset()
if not CC.longActive:
self.LoC.reset(v_pid=CS.vEgo)
self.LoC.reset()
if not self.joystick_mode:
# accel PID loop
pid_accel_limits = self.CI.get_pid_accel_limits(self.CP, CS.vEgo, self.v_cruise_helper.v_cruise_kph * CV.KPH_TO_MS)
t_since_plan = (self.sm.frame - self.sm.recv_frame['longitudinalPlan']) * DT_CTRL
actuators.accel = self.LoC.update(CC.longActive, CS, long_plan, pid_accel_limits, t_since_plan)
actuators.accel = self.LoC.update(CC.longActive, CS, long_plan.aTarget, long_plan.shouldStop, pid_accel_limits)
# Steering PID loop and lateral MPC
if self.model_use_lateral_planner:
@@ -831,7 +830,6 @@ class Controls:
controlsState.state = self.state
controlsState.engageable = not self.events.contains(ET.NO_ENTRY)
controlsState.longControlState = self.LoC.long_control_state
controlsState.vPid = float(self.LoC.v_pid)
controlsState.vCruise = float(self.v_cruise_helper.v_cruise_kph)
controlsState.vCruiseCluster = float(self.v_cruise_helper.v_cruise_cluster_kph)
controlsState.upAccelCmd = float(self.LoC.pid.p)
@@ -931,7 +929,7 @@ class Controls:
while True:
self.step()
self.rk.monitor_time()
except SystemExit:
finally:
e.set()
t.join()
-10
View File
@@ -237,16 +237,6 @@ class VCruiseHelper:
self.is_metric_prev = is_metric
def apply_deadzone(error, deadzone):
if error > deadzone:
error -= deadzone
elif error < - deadzone:
error += deadzone
else:
error = 0.
return error
def apply_center_deadzone(error, deadzone):
if (error > - deadzone) and (error < deadzone):
error = 0.
+1 -1
View File
@@ -7,7 +7,7 @@ from openpilot.common.filter_simple import FirstOrderFilter
from openpilot.common.numpy_fast import interp
from openpilot.selfdrive.car.interfaces import LatControlInputs
from openpilot.common.params import Params
from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N, apply_deadzone
from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N
from openpilot.selfdrive.controls.lib.latcontrol import LatControl
from openpilot.selfdrive.controls.lib.pid import PIDController
from openpilot.selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY
+18 -66
View File
@@ -1,7 +1,7 @@
from cereal import car
from openpilot.common.numpy_fast import clip, interp
from openpilot.common.numpy_fast import clip
from openpilot.common.realtime import DT_CTRL
from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N, apply_deadzone
from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N
from openpilot.selfdrive.controls.lib.pid import PIDController
from openpilot.selfdrive.modeld.constants import ModelConstants
@@ -10,20 +10,12 @@ CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N]
LongCtrlState = car.CarControl.Actuators.LongControlState
def long_control_state_trans(CP, active, long_control_state, v_ego, v_target,
v_target_1sec, brake_pressed, cruise_standstill):
def long_control_state_trans(CP, active, long_control_state, v_ego,
should_stop, brake_pressed, cruise_standstill):
# Ignore cruise standstill if car has a gas interceptor
cruise_standstill = cruise_standstill and not CP.enableGasInterceptorDEPRECATED
accelerating = v_target_1sec > v_target
planned_stop = (v_target < CP.vEgoStopping and
v_target_1sec < CP.vEgoStopping and
not accelerating)
stay_stopped = (v_ego < CP.vEgoStopping and
(brake_pressed or cruise_standstill))
stopping_condition = planned_stop or stay_stopped
starting_condition = (v_target_1sec > CP.vEgoStarting and
accelerating and
stopping_condition = should_stop
starting_condition = (not should_stop and
not cruise_standstill and
not brake_pressed)
started_condition = v_ego > CP.vEgoStarting
@@ -36,7 +28,6 @@ def long_control_state_trans(CP, active, long_control_state, v_ego, v_target,
long_control_state = LongCtrlState.pid
if stopping_condition:
long_control_state = LongCtrlState.stopping
elif long_control_state == LongCtrlState.stopping:
if starting_condition and CP.startingState:
long_control_state = LongCtrlState.starting
@@ -51,84 +42,45 @@ def long_control_state_trans(CP, active, long_control_state, v_ego, v_target,
return long_control_state
class LongControl:
def __init__(self, CP):
self.CP = CP
self.long_control_state = LongCtrlState.off # initialized to off
self.long_control_state = LongCtrlState.off
self.pid = PIDController((CP.longitudinalTuning.kpBP, CP.longitudinalTuning.kpV),
(CP.longitudinalTuning.kiBP, CP.longitudinalTuning.kiV),
k_f=CP.longitudinalTuning.kf, rate=1 / DT_CTRL)
self.v_pid = 0.0
self.last_output_accel = 0.0
def reset(self, v_pid):
"""Reset PID controller and change setpoint"""
def reset(self):
self.pid.reset()
self.v_pid = v_pid
def update(self, active, CS, long_plan, accel_limits, t_since_plan):
def update(self, active, CS, a_target, should_stop, accel_limits):
"""Update longitudinal control. This updates the state machine and runs a PID loop"""
# Interp control trajectory
speeds = long_plan.speeds
if len(speeds) == CONTROL_N:
v_target_now = interp(t_since_plan, CONTROL_N_T_IDX, speeds)
a_target_now = interp(t_since_plan, CONTROL_N_T_IDX, long_plan.accels)
v_target_lower = interp(self.CP.longitudinalActuatorDelayLowerBound + t_since_plan, CONTROL_N_T_IDX, speeds)
a_target_lower = 2 * (v_target_lower - v_target_now) / self.CP.longitudinalActuatorDelayLowerBound - a_target_now
v_target_upper = interp(self.CP.longitudinalActuatorDelayUpperBound + t_since_plan, CONTROL_N_T_IDX, speeds)
a_target_upper = 2 * (v_target_upper - v_target_now) / self.CP.longitudinalActuatorDelayUpperBound - a_target_now
v_target = min(v_target_lower, v_target_upper)
a_target = min(a_target_lower, a_target_upper)
v_target_1sec = interp(self.CP.longitudinalActuatorDelayUpperBound + t_since_plan + 1.0, CONTROL_N_T_IDX, speeds)
else:
v_target = 0.0
v_target_now = 0.0
v_target_1sec = 0.0
a_target = 0.0
self.pid.neg_limit = accel_limits[0]
self.pid.pos_limit = accel_limits[1]
output_accel = self.last_output_accel
self.long_control_state = long_control_state_trans(self.CP, active, self.long_control_state, CS.vEgo,
v_target, v_target_1sec, CS.brakePressed,
should_stop, CS.brakePressed,
CS.cruiseState.standstill)
if self.long_control_state == LongCtrlState.off:
self.reset(CS.vEgo)
self.reset()
output_accel = 0.
elif self.long_control_state == LongCtrlState.stopping:
output_accel = self.last_output_accel
if output_accel > self.CP.stopAccel:
output_accel = min(output_accel, 0.0)
output_accel -= self.CP.stoppingDecelRate * DT_CTRL
self.reset(CS.vEgo)
self.reset()
elif self.long_control_state == LongCtrlState.starting:
output_accel = self.CP.startAccel
self.reset(CS.vEgo)
self.reset()
elif self.long_control_state == LongCtrlState.pid:
self.v_pid = v_target_now
# Toyota starts braking more when it thinks you want to stop
# Freeze the integrator so we don't accelerate to compensate, and don't allow positive acceleration
# TODO too complex, needs to be simplified and tested on toyotas
prevent_overshoot = not self.CP.stoppingControl and CS.vEgo < 1.5 and v_target_1sec < 0.7 and v_target_1sec < self.v_pid
deadzone = interp(CS.vEgo, self.CP.longitudinalTuning.deadzoneBP, self.CP.longitudinalTuning.deadzoneV)
freeze_integrator = prevent_overshoot
error = self.v_pid - CS.vEgo
error_deadzone = apply_deadzone(error, deadzone)
output_accel = self.pid.update(error_deadzone, speed=CS.vEgo,
feedforward=a_target,
freeze_integrator=freeze_integrator)
else: # LongCtrlState.pid
error = a_target - CS.aEgo
output_accel = self.pid.update(error, speed=CS.vEgo,
feedforward=a_target)
self.last_output_accel = clip(output_accel, accel_limits[0], accel_limits[1])
return self.last_output_accel
+31 -2
View File
@@ -27,6 +27,7 @@ LON_MPC_STEP = 0.2 # first step is 0.2s
A_CRUISE_MIN = -1.2
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]
# Lookup table for turns
_A_TOTAL_MAX_V = [1.7, 3.2]
@@ -45,7 +46,6 @@ def limit_accel_in_turns(v_ego, angle_steers, a_target, CP):
This function returns a limited long acceleration allowed, depending on the existing lateral acceleration
this should avoid accelerating when losing the target in turns
"""
# FIXME: This function to calculate lateral accel is incorrect and should use the VehicleModel
# The lookup table for turns should also be updated if we do this
a_total_max = interp(v_ego, _A_TOTAL_MAX_BP, _A_TOTAL_MAX_V)
@@ -55,6 +55,26 @@ def limit_accel_in_turns(v_ego, angle_steers, a_target, CP):
return [a_target[0], min(a_target[1], a_x_allowed)]
def get_accel_from_plan(CP, long_plan):
speeds = long_plan.speeds
if len(speeds) == CONTROL_N:
v_target_now = interp(DT_MDL, CONTROL_N_T_IDX, speeds)
a_target_now = interp(DT_MDL, CONTROL_N_T_IDX, long_plan.accels)
v_target = interp(CP.longitudinalActuatorDelay + DT_MDL, CONTROL_N_T_IDX, speeds)
a_target = 2 * (v_target - v_target_now) / CP.longitudinalActuatorDelay - a_target_now
v_target_1sec = interp(CP.longitudinalActuatorDelay + DT_MDL + 1.0, CONTROL_N_T_IDX, speeds)
else:
v_target = 0.0
v_target_now = 0.0
v_target_1sec = 0.0
a_target = 0.0
should_stop = (v_target < CP.vEgoStopping and
v_target_1sec < CP.vEgoStopping)
return a_target, should_stop
class LongitudinalPlanner:
def __init__(self, CP, init_v=0.0, init_a=0.0, dt=DT_MDL):
self.CP = CP
@@ -183,9 +203,14 @@ class LongitudinalPlanner:
plan_send.valid = sm.all_checks(service_list=['carState', 'controlsState'])
longitudinalPlan = plan_send.longitudinalPlan
longitudinalPlan.modelMonoTime = sm.logMonoTime['modelV2']
longitudinalPlan.processingDelay = (plan_send.logMonoTime / 1e9) - sm.logMonoTime['modelV2']
longitudinalPlan.solverExecutionTime = self.mpc.solve_time
longitudinalPlan.allowBrake = True
longitudinalPlan.allowThrottle = True
longitudinalPlan.speeds = self.v_desired_trajectory.tolist()
longitudinalPlan.accels = self.a_desired_trajectory.tolist()
@@ -195,7 +220,11 @@ class LongitudinalPlanner:
longitudinalPlan.longitudinalPlanSource = self.mpc.source
longitudinalPlan.fcw = self.fcw
longitudinalPlan.solverExecutionTime = self.mpc.solve_time
a_target, should_stop = get_accel_from_plan(self.CP, longitudinalPlan)
longitudinalPlan.aTarget = a_target
longitudinalPlan.shouldStop = should_stop
longitudinalPlan.allowBrake = True
longitudinalPlan.allowThrottle = True
pm.send('longitudinalPlan', plan_send)
+2 -23
View File
@@ -13,27 +13,6 @@ from openpilot.selfdrive.sunnypilot import get_model_generation
import cereal.messaging as messaging
def cumtrapz(x, t):
return np.concatenate([[0], np.cumsum(((x[0:-1] + x[1:])/2) * np.diff(t))])
def publish_ui_plan(sm, pm, lateral_planner, longitudinal_planner, model_use_lateral_planner):
if model_use_lateral_planner:
plan_odo = cumtrapz(longitudinal_planner.v_desired_trajectory_full, ModelConstants.T_IDXS)
model_odo = cumtrapz(lateral_planner.v_plan, ModelConstants.T_IDXS)
ui_send = messaging.new_message('uiPlan')
ui_send.valid = sm.all_checks(service_list=['carState', 'controlsState', 'modelV2'])
uiPlan = ui_send.uiPlan
uiPlan.frameId = sm['modelV2'].frameId
if model_use_lateral_planner:
x_fp = (lateral_planner.x_sol if lateral_planner.dynamic_lane_profile_status else lateral_planner.lat_mpc.x_sol)[:,0]
y_fp = (lateral_planner.x_sol if lateral_planner.dynamic_lane_profile_status else lateral_planner.lat_mpc.x_sol)[:,1]
uiPlan.position.x = np.interp(plan_odo, model_odo, x_fp).tolist() if model_use_lateral_planner else list(sm['modelV2'].position.x)
uiPlan.position.y = np.interp(plan_odo, model_odo, y_fp).tolist() if model_use_lateral_planner else list(sm['modelV2'].position.y)
uiPlan.position.z = np.interp(plan_odo, model_odo, lateral_planner.path_xyz[:,2]).tolist() if model_use_lateral_planner else list(sm['modelV2'].position.z)
uiPlan.accel = longitudinal_planner.a_desired_trajectory_full.tolist()
pm.send('uiPlan', ui_send)
def plannerd_thread():
config_realtime_process(5, Priority.CTRL_LOW)
@@ -53,7 +32,7 @@ def plannerd_thread():
lateral_planner = LateralPlanner(CP, debug=debug_mode, model_use_lateral_planner=model_use_lateral_planner)
lateral_planner_svs = ['lateralPlanDEPRECATED', 'lateralPlanSPDEPRECATED']
pm = messaging.PubMaster(['longitudinalPlan', 'uiPlan', 'longitudinalPlanSP'] + lateral_planner_svs)
pm = messaging.PubMaster(['longitudinalPlan', 'longitudinalPlanSP'] + lateral_planner_svs)
sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'radarState', 'modelV2',
'longitudinalPlan', 'navInstruction', 'longitudinalPlanSP',
'liveMapDataSP', 'e2eLongStateSP'] + lateral_planner_svs,
@@ -66,7 +45,7 @@ def plannerd_thread():
lateral_planner.publish(sm, pm)
longitudinal_planner.update(sm)
longitudinal_planner.publish(sm, pm)
publish_ui_plan(sm, pm, lateral_planner, longitudinal_planner, model_use_lateral_planner)
def main():
plannerd_thread()
+20 -26
View File
@@ -5,24 +5,35 @@ from collections import defaultdict
import matplotlib.pyplot as plt
from cereal.services import SERVICE_LIST
from openpilot.tools.lib.logreader import LogReader
from openpilot.tools.lib.route import Route
from tqdm import tqdm
MIN_SIZE = 0.5 # Percent size of total to show as separate entry
def make_pie(msgs, typ):
compressed_length_by_type = {k: len(bz2.compress(b"".join(v))) for k, v in msgs.items()}
msgs_by_type = defaultdict(list)
for m in msgs:
msgs_by_type[m.which()].append(m.as_builder().to_bytes())
total = sum(compressed_length_by_type.values())
total = len(bz2.compress(b"".join([m.as_builder().to_bytes() for m in msgs])))
uncompressed_total = len(b"".join([m.as_builder().to_bytes() for m in msgs]))
length_by_type = {k: len(b"".join(v)) for k, v in msgs_by_type.items()}
# calculate compressed size by calculating diff when removed from the segment
compressed_length_by_type = {}
for k in tqdm(msgs_by_type.keys(), desc="Compressing"):
compressed_length_by_type[k] = total - len(bz2.compress(b"".join([m.as_builder().to_bytes() for m in msgs if m.which() != k])))
sizes = sorted(compressed_length_by_type.items(), key=lambda kv: kv[1])
print(f"{typ} - Total {total / 1024:.2f} kB")
print("name - comp. size (uncomp. size)")
for (name, sz) in sizes:
print(f"{name} - {sz / 1024:.2f} kB")
print(f"{name:<22} - {sz / 1024:.2f} kB ({length_by_type[name] / 1024:.2f} kB)")
print()
print(f"{typ} - Real total {total / 1024:.2f} kB")
print(f"{typ} - Breakdown total {sum(compressed_length_by_type.values()) / 1024:.2f} kB")
print(f"{typ} - Uncompressed total {uncompressed_total / 1024 / 1024:.2f} MB")
sizes_large = [(k, sz) for (k, sz) in sizes if sz >= total * MIN_SIZE / 100]
sizes_large += [('other', sum(sz for (_, sz) in sizes if sz < total * MIN_SIZE / 100))]
@@ -35,28 +46,11 @@ def make_pie(msgs, typ):
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Check qlog size based on a rlog')
parser = argparse.ArgumentParser(description='View log size breakdown by message type')
parser.add_argument('route', help='route to use')
parser.add_argument('segment', type=int, help='segment number to use')
args = parser.parse_args()
r = Route(args.route)
rlog = r.log_paths()[args.segment]
msgs = list(LogReader(rlog))
msgs = list(LogReader(args.route))
msgs_by_type = defaultdict(list)
for m in msgs:
msgs_by_type[m.which()].append(m.as_builder().to_bytes())
qlog_by_type = defaultdict(list)
for name, service in SERVICE_LIST.items():
if service.decimation is None:
continue
for i, msg in enumerate(msgs_by_type[name]):
if i % service.decimation == 0:
qlog_by_type[name].append(msg)
make_pie(msgs_by_type, 'rlog')
make_pie(qlog_by_type, 'qlog')
make_pie(msgs, 'qlog')
plt.show()
+6 -6
View File
@@ -6,7 +6,7 @@ import numpy as np
import cereal.messaging as messaging
from cereal import car, log
from pathlib import Path
from setproctitle import setproctitle
from openpilot.common.threadname import setthreadname
from cereal.messaging import PubMaster, SubMaster
from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf
from openpilot.common.swaglog import cloudlog
@@ -29,7 +29,7 @@ from openpilot.selfdrive.modeld.models.commonmodel_pyx import ModelFrame, CLCont
from openpilot.selfdrive.sunnypilot import get_model_generation
from openpilot.system.hardware.hw import Paths
PROCESS_NAME = "selfdrive.modeld.modeld"
THREAD_NAME = "selfdrive.modeld.modeld"
SEND_RAW_PRED = os.getenv('SEND_RAW_PRED')
MODEL_PATHS = {
@@ -170,9 +170,9 @@ class ModelState:
def main(demo=False):
cloudlog.warning("modeld init")
sentry.set_tag("daemon", PROCESS_NAME)
cloudlog.bind(daemon=PROCESS_NAME)
setproctitle(PROCESS_NAME)
sentry.set_tag("daemon", THREAD_NAME)
cloudlog.bind(daemon=THREAD_NAME)
setthreadname("modeld")
config_realtime_process(7, 54)
cloudlog.warning("setting up CL context")
@@ -409,7 +409,7 @@ if __name__ == "__main__":
args = parser.parse_args()
main(demo=args.demo)
except KeyboardInterrupt:
cloudlog.warning(f"child {PROCESS_NAME} got SIGINT")
cloudlog.warning(f"child {THREAD_NAME} got SIGINT")
except Exception:
sentry.capture_exception()
raise
+1 -1
View File
@@ -120,7 +120,7 @@ std::vector<std::string> PandaUsbHandle::list() {
libusb_close(handle);
if (ret < 0) { goto finish; }
serials.push_back(std::string((char *)desc_serial, ret).c_str());
serials.push_back(std::string((char *)desc_serial, ret));
}
}
+2 -2
View File
@@ -84,8 +84,8 @@ class TestBoarddSpi:
ps = m.peripheralState
assert ps.pandaType == "tres"
assert 4000 < ps.voltage < 14000
assert 100 < ps.current < 1000
assert ps.fanSpeedRpm < 8000
assert 50 < ps.current < 1000
assert ps.fanSpeedRpm < 10000
time.sleep(0.5)
et = time.monotonic() - st
@@ -505,7 +505,7 @@ CONFIGS = [
ProcessConfig(
proc_name="plannerd",
pubs=["modelV2", "carControl", "carState", "controlsState", "radarState"],
subs=["longitudinalPlan", "uiPlan"],
subs=["longitudinalPlan"],
ignore=["logMonoTime", "longitudinalPlan.processingDelay", "longitudinalPlan.solverExecutionTime"],
init_callback=get_car_params_callback,
should_recv_callback=FrequencyBasedRcvCallback("modelV2"),
+1 -1
View File
@@ -1 +1 @@
e536df5586a71b22baa789dc584d7eab67f1fbbb
8737e368e17f859291164286feb4246e00c0b4a5
+16 -16
View File
@@ -36,26 +36,26 @@ PROCS = {
# Baseline CPU usage by process
"selfdrive.controls.controlsd": 32.0,
"selfdrive.car.card": 22.0,
"./loggerd": 14.0,
"./encoderd": 17.0,
"./camerad": 14.5,
"./locationd": 11.0,
"loggerd": 14.0,
"encoderd": 17.0,
"camerad": 14.5,
"locationd": 11.0,
"selfdrive.controls.plannerd": 11.0,
"./ui": 18.0,
"ui": 18.0,
"selfdrive.locationd.paramsd": 9.0,
"./sensord": 7.0,
"sensord": 7.0,
"selfdrive.controls.radard": 7.0,
"selfdrive.modeld.modeld": 13.0,
"modeld": 13.0,
"selfdrive.modeld.dmonitoringmodeld": 8.0,
"system.hardware.hardwared": 3.87,
"selfdrive.locationd.calibrationd": 2.0,
"selfdrive.locationd.torqued": 5.0,
"selfdrive.ui.soundd": 3.5,
"selfdrive.monitoring.dmonitoringd": 4.0,
"./proclogd": 1.54,
"proclogd": 1.54,
"system.logmessaged": 0.2,
"system.tombstoned": 0,
"./logcatd": 0,
"logcatd": 0,
"system.micd": 6.0,
"system.timed": 0,
"selfdrive.pandad.pandad": 0,
@@ -67,12 +67,12 @@ PROCS = {
PROCS.update({
"tici": {
"./pandad": 4.0,
"./ubloxd": 0.02,
"pandad": 4.0,
"ubloxd": 0.02,
"system.ubloxd.pigeond": 6.0,
},
"tizi": {
"./pandad": 19.0,
"pandad": 19.0,
"system.qcomgpsd.qcomgpsd": 1.0,
}
}.get(HARDWARE.get_device_type(), {}))
@@ -247,8 +247,7 @@ class TestOnroad:
for pl in self.service_msgs['procLog']:
for x in pl.procLog.procs:
if len(x.cmdline) > 0:
n = list(x.cmdline)[0]
plogs_by_proc[n].append(x)
plogs_by_proc[x.name].append(x)
print(plogs_by_proc.keys())
cpu_ok = True
@@ -256,8 +255,9 @@ class TestOnroad:
for proc_name, expected_cpu in PROCS.items():
err = ""
exp = "???"
cpu_usage = 0.
x = plogs_by_proc[proc_name]
x = plogs_by_proc[proc_name[-15:]]
if len(x) > 2:
cpu_time = cputime_total(x[-1]) - cputime_total(x[0])
cpu_usage = cpu_time / dt * 100.
@@ -309,7 +309,7 @@ class TestOnroad:
assert max(mems) - min(mems) <= 3.0
def test_gpu_usage(self):
assert self.gpu_procs == {"weston", "ui", "camerad", "selfdrive.modeld.modeld"}
assert self.gpu_procs == {"weston", "ui", "camerad", "modeld"}
def test_camera_processing_time(self):
result = "\n"
+1 -1
View File
@@ -164,7 +164,7 @@ class TestUpdated:
# make sure LastUpdateTime is recent
t = self._read_param("LastUpdateTime")
last_update_time = datetime.datetime.fromisoformat(t)
td = datetime.datetime.utcnow() - last_update_time
td = datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - last_update_time
assert td.total_seconds() < 10
self.params.remove("LastUpdateTime")
+3 -4
View File
@@ -1370,7 +1370,7 @@ void AnnotatedCameraWidget::drawLaneLines(QPainter &painter, const UIState *s) {
}
// paint path
QLinearGradient bg(0, height(), 0, height() / 4);
QLinearGradient bg(0, height(), 0, 0);
if (madsEnabled || car_state.getCruiseState().getEnabled()) {
if (steerOverride && latActive) {
bg.setColorAt(0.0, QColor::fromHslF(20 / 360., 0.94, 0.51, 0.17));
@@ -1381,8 +1381,7 @@ void AnnotatedCameraWidget::drawLaneLines(QPainter &painter, const UIState *s) {
bg.setColorAt(1, whiteColor(0));
} else if (sm["controlsState"].getControlsState().getExperimentalMode()) {
// The first half of track_vertices are the points for the right side of the path
// and the indices match the positions of accel from uiPlan
const auto &acceleration = sm["uiPlan"].getUiPlan().getAccel();
const auto &acceleration = sm["modelV2"].getModelV2().getAcceleration().getX();
const int max_len = std::min<int>(scene.track_vertices.length() / 2, acceleration.size());
for (int i = 0; i < max_len; ++i) {
@@ -1650,7 +1649,7 @@ void AnnotatedCameraWidget::paintEvent(QPaintEvent *event) {
painter.setPen(Qt::NoPen);
if (s->scene.world_objects_visible) {
update_model(s, model, sm["uiPlan"].getUiPlan());
update_model(s, model);
drawLaneLines(painter, s);
if (s->scene.longitudinal_control && sm.rcv_frame("radarState") > s->scene.started_frame) {
+8 -13
View File
@@ -78,14 +78,10 @@ void update_line_data(const UIState *s, const cereal::XYZTData::Reader &line,
}
void update_model(UIState *s,
const cereal::ModelDataV2::Reader &model,
const cereal::UiPlan::Reader &plan) {
const cereal::ModelDataV2::Reader &model) {
UIScene &scene = s->scene;
auto plan_position = plan.getPosition();
if (plan_position.getX().size() < model.getPosition().getX().size()) {
plan_position = model.getPosition();
}
float max_distance = std::clamp(*(plan_position.getX().end() - 1),
auto model_position = model.getPosition();
float max_distance = std::clamp(*(model_position.getX().end() - 1),
MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE);
// update lane lines
@@ -117,9 +113,9 @@ void update_model(UIState *s,
const float lead_d = lead_one.getDRel() * 2.;
max_distance = std::clamp((float)(lead_d - fmin(lead_d * 0.35, 10.)), 0.0f, max_distance);
}
max_idx = get_path_length_idx(plan_position, max_distance);
update_line_data(s, plan_position, 0.9 - scene.mads_path_range * scene.mads_path_scale, 1.22, 1.22, &scene.track_vertices, max_idx, false);
update_line_data(s, plan_position, 1.0 - scene.mads_path_range * scene.mads_path_scale - 0.1 * scene.mads_path_scale, 1.22, 1.22, &scene.track_edge_vertices, max_idx, false);
max_idx = get_path_length_idx(model_position, max_distance);
update_line_data(s, model_position, 0.9 - scene.mads_path_range * scene.mads_path_scale, 1.22, 1.22, &scene.track_vertices, max_idx, false);
update_line_data(s, model_position, 1.0 - scene.mads_path_range * scene.mads_path_scale - 0.1 * scene.mads_path_scale, 1.22, 1.22, &scene.track_edge_vertices, max_idx, false);
}
void update_dmonitoring(UIState *s, const cereal::DriverStateV2::Reader &driverstate, float dm_fade_state, bool is_rhd) {
@@ -221,8 +217,7 @@ static void update_state(UIState *s) {
scene.world_objects_visible = scene.world_objects_visible ||
(scene.started &&
sm.rcv_frame("liveCalibration") > scene.started_frame &&
sm.rcv_frame("modelV2") > scene.started_frame &&
sm.rcv_frame("uiPlan") > scene.started_frame);
sm.rcv_frame("modelV2") > scene.started_frame);
// TODO: SP - Set this dynamically on init with manual toggle or driving model selection
if (sm.updated("lateralPlanSPDEPRECATED")) {
scene.dynamic_lane_profile_status = sm["lateralPlanSPDEPRECATED"].getLateralPlanSPDEPRECATED().getDynamicLaneProfileStatus();
@@ -392,7 +387,7 @@ UIState::UIState(QObject *parent) : QObject(parent) {
sm = std::make_unique<SubMaster, const std::initializer_list<const char *>>({
"modelV2", "controlsState", "liveCalibration", "radarState", "deviceState",
"pandaStates", "carParams", "driverMonitoringState", "carState", "liveLocationKalman", "driverStateV2",
"wideRoadCameraState", "managerState", "navInstruction", "navRoute", "uiPlan", "clocks", "longitudinalPlanSP", "liveMapDataSP",
"wideRoadCameraState", "managerState", "navInstruction", "navRoute", "clocks", "longitudinalPlanSP", "liveMapDataSP",
"carControl", "lateralPlanSPDEPRECATED", "gpsLocation", "gpsLocationExternal", "liveParameters", "liveTorqueParameters", "controlsStateSP"
});
+1 -2
View File
@@ -334,8 +334,7 @@ Device *device();
void ui_update_params(UIState *s);
int get_path_length_idx(const cereal::XYZTData::Reader &line, const float path_height);
void update_model(UIState *s,
const cereal::ModelDataV2::Reader &model,
const cereal::UiPlan::Reader &plan);
const cereal::ModelDataV2::Reader &model);
void update_dmonitoring(UIState *s, const cereal::DriverStateV2::Reader &driverstate, float dm_fade_state, bool is_rhd);
void update_leads(UIState *s, const cereal::RadarState::Reader &radar_state, const cereal::XYZTData::Reader &line);
void update_line_data(const UIState *s, const cereal::XYZTData::Reader &line,
+2 -2
View File
@@ -4,7 +4,7 @@ import json
import jwt
from pathlib import Path
from datetime import datetime, timedelta
from datetime import datetime, timedelta, UTC
from openpilot.common.api import api_get
from openpilot.common.api.sunnylink import SunnylinkApi
from openpilot.common.params import Params
@@ -67,7 +67,7 @@ def register(show_spinner=False) -> str | None:
start_time = time.monotonic()
while True:
try:
register_token = jwt.encode({'register': True, 'exp': datetime.utcnow() + timedelta(hours=1)}, private_key, algorithm='RS256')
register_token = jwt.encode({'register': True, 'exp': datetime.now(UTC).replace(tzinfo=None) + timedelta(hours=1)}, private_key, algorithm='RS256')
cloudlog.info("getting pilotauth")
resp = api_get("v2/pilotauth/", method='POST', timeout=15,
imei=imei1, imei2=imei2, serial=serial, public_key=public_key, register_token=register_token)
+1 -1
View File
@@ -111,7 +111,7 @@ def manager_init() -> None:
("LastSunnylinkPingTime", "0"),
]
if not PC:
default_params.append(("LastUpdateTime", datetime.datetime.utcnow().isoformat().encode('utf8')))
default_params.append(("LastUpdateTime", datetime.datetime.now(datetime.UTC).replace(tzinfo=None).isoformat().encode('utf8')))
if params.get_bool("RecordFrontLock"):
params.put_bool("RecordFront", True)
+2 -2
View File
@@ -8,7 +8,7 @@ from collections.abc import Callable, ValuesView
from abc import ABC, abstractmethod
from multiprocessing import Process
from setproctitle import setproctitle
from openpilot.common.threadname import setthreadname
from cereal import car, log
import cereal.messaging as messaging
@@ -27,7 +27,7 @@ def launcher(proc: str, name: str) -> None:
mod = importlib.import_module(proc)
# rename the process
setproctitle(proc)
setthreadname(proc)
# create new context since we forked
messaging.context = messaging.Context()
+1 -1
View File
@@ -173,7 +173,7 @@ def setup_quectel(diag: ModemDiag) -> bool:
os.remove(ASSIST_DATA_FILE)
#at_cmd("AT+QGPSXTRADATA?")
if system_time_valid():
time_str = datetime.datetime.utcnow().strftime("%Y/%m/%d,%H:%M:%S")
time_str = datetime.datetime.now(datetime.UTC).replace(tzinfo=None).strftime("%Y/%m/%d,%H:%M:%S")
at_cmd(f"AT+QGPSXTRATIME=0,\"{time_str}\",1,1,1000")
at_cmd("AT+QGPSCFG=\"outport\",\"usbnmea\"")
+1 -1
View File
@@ -85,7 +85,7 @@ class TestRawgpsd:
if should_be_loaded:
assert valid_duration == "10080" # should be max time
injected_time = datetime.datetime.strptime(injected_time_str.replace("\"", ""), "%Y/%m/%d,%H:%M:%S")
assert abs((datetime.datetime.utcnow() - injected_time).total_seconds()) < 60*60*12
assert abs((datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - injected_time).total_seconds()) < 60*60*12
else:
valid_duration, injected_time_str = out.split(",", 1)
injected_time_str = injected_time_str.replace('\"', '').replace('\'', '')
+1 -1
View File
@@ -133,7 +133,7 @@ def main() -> NoReturn:
# flush when started state changes or after FLUSH_TIME_S
if (time.monotonic() > last_flush_time + STATS_FLUSH_TIME_S) or (sm['deviceState'].started != started_prev):
result = ""
current_time = datetime.utcnow().replace(tzinfo=UTC)
current_time = datetime.now(UTC)
tags['started'] = sm['deviceState'].started
for key, value in gauges.items():
+2 -2
View File
@@ -6,7 +6,7 @@ import serial
import struct
import requests
import urllib.parse
from datetime import datetime
from datetime import datetime, UTC
from cereal import messaging
from openpilot.common.params import Params
@@ -196,7 +196,7 @@ def initialize_pigeon(pigeon: TTYPigeon) -> bool:
cloudlog.error(f"failed to restore almanac backup, status: {restore_status}")
# sending time to ublox
t_now = datetime.utcnow()
t_now = datetime.now(UTC).replace(tzinfo=None)
if t_now >= datetime(2021, 6, 1):
cloudlog.warning("Sending current time to ublox")
+5 -5
View File
@@ -60,7 +60,7 @@ class WaitTimeHelper:
self.ready_event.wait(timeout=t)
def write_time_to_param(params, param) -> None:
t = datetime.datetime.utcnow()
t = datetime.datetime.now(datetime.UTC).replace(tzinfo=None)
params.put(param, t.isoformat().encode('utf8'))
def read_time_from_param(params, param) -> datetime.datetime | None:
@@ -279,7 +279,7 @@ class Updater:
if len(self.branches):
self.params.put("UpdaterAvailableBranches", ','.join(self.branches.keys()))
last_update = datetime.datetime.utcnow()
last_update = datetime.datetime.now(datetime.UTC).replace(tzinfo=None)
if update_success:
write_time_to_param(self.params, "LastUpdateTime")
else:
@@ -323,7 +323,7 @@ class Updater:
for alert in ("Offroad_UpdateFailed", "Offroad_ConnectivityNeeded", "Offroad_ConnectivityNeededPrompt"):
set_offroad_alert(alert, False)
now = datetime.datetime.utcnow()
now = datetime.datetime.now(datetime.UTC).replace(tzinfo=None)
dt = now - last_update
build_metadata = get_build_metadata()
if failed_count > 15 and exception is not None and self.has_internet:
@@ -429,7 +429,7 @@ def main() -> None:
cloudlog.event("update installed")
if not params.get("InstallDate"):
t = datetime.datetime.utcnow().isoformat()
t = datetime.datetime.now(datetime.UTC).replace(tzinfo=None).isoformat()
params.put("InstallDate", t.encode('utf8'))
updater = Updater()
@@ -469,7 +469,7 @@ def main() -> None:
# download update
last_fetch = read_time_from_param(params, "UpdaterLastFetchTime")
timed_out = last_fetch is None or (datetime.datetime.utcnow() - last_fetch > datetime.timedelta(days=3))
timed_out = last_fetch is None or (datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - last_fetch > datetime.timedelta(days=3))
user_requested_fetch = wait_helper.user_request == UserRequest.FETCH
if params.get_bool("NetworkMetered") and not timed_out and not user_requested_fetch:
cloudlog.info("skipping fetch, connection metered")
@@ -3,6 +3,7 @@ import json
# for aiortc and its dependencies
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
warnings.filterwarnings("ignore", category=RuntimeWarning) # TODO: remove this when google-crc32c publish a python3.12 wheel
from aiortc import RTCDataChannel
from aiortc.mediastreams import VIDEO_CLOCK_RATE, VIDEO_TIME_BASE
+1
View File
@@ -4,6 +4,7 @@ import json
# for aiortc and its dependencies
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
warnings.filterwarnings("ignore", category=RuntimeWarning) # TODO: remove this when google-crc32c publish a python3.12 wheel
from openpilot.system.webrtc.webrtcd import get_stream
+1
View File
@@ -11,6 +11,7 @@ from typing import Any, TYPE_CHECKING
# aiortc and its dependencies have lots of internal warnings :(
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
warnings.filterwarnings("ignore", category=RuntimeWarning) # TODO: remove this when google-crc32c publish a python3.12 wheel
import capnp
from aiohttp import web
+1 -1
View File
@@ -277,7 +277,7 @@ void ChartView::updateSeriesPoints() {
}
((QScatterSeries *)s.series)->setMarkerSize(size);
} else {
s.series->setPointsVisible(pixels_per_point > 20);
s.series->setPointsVisible(num_points == 1 || pixels_per_point > 20);
}
}
}
+7 -2
View File
@@ -6,6 +6,7 @@ import argparse
import numpy as np
import multiprocessing
import time
import signal
import cereal.messaging as messaging
from msgq.visionipc import VisionIpcServer, VisionStreamType
@@ -18,8 +19,8 @@ V4L2_BUF_FLAG_KEYFRAME = 8
ENCODE_SOCKETS = {
VisionStreamType.VISION_STREAM_ROAD: "roadEncodeData",
VisionStreamType.VISION_STREAM_WIDE_ROAD: "wideRoadEncodeData",
VisionStreamType.VISION_STREAM_DRIVER: "driverEncodeData",
VisionStreamType.VISION_STREAM_WIDE_ROAD: "wideRoadEncodeData",
}
def decoder(addr, vipc_server, vst, nvidia, W, H, debug=False):
@@ -147,10 +148,14 @@ if __name__ == "__main__":
vision_streams = [
VisionStreamType.VISION_STREAM_ROAD,
VisionStreamType.VISION_STREAM_WIDE_ROAD,
VisionStreamType.VISION_STREAM_DRIVER,
VisionStreamType.VISION_STREAM_WIDE_ROAD,
]
vsts = [vision_streams[int(x)] for x in args.cams.split(",")]
cvipc = CompressedVipc(args.addr, vsts, args.nvidia, debug=(not args.silent))
# register exit handler
signal.signal(signal.SIGINT, lambda sig, frame: cvipc.kill())
cvipc.join()
+1 -1
View File
@@ -41,7 +41,7 @@ fi
export MAKEFLAGS="-j$(nproc)"
PYENV_PYTHON_VERSION=$(cat $ROOT/.python-version)
PYENV_PYTHON_VERSION="3.12.4"
if ! pyenv prefix ${PYENV_PYTHON_VERSION} &> /dev/null; then
# no pyenv update on mac
if [ "$(uname)" == "Linux" ]; then
+2 -2
View File
@@ -1,5 +1,5 @@
import os
from datetime import datetime, timedelta
from datetime import datetime, timedelta, UTC
from functools import lru_cache
from pathlib import Path
from typing import IO
@@ -20,7 +20,7 @@ def get_azure_credential():
@lru_cache
def get_container_sas(account_name: str, container_name: str):
from azure.storage.blob import BlobServiceClient, ContainerSasPermissions, generate_container_sas
start_time = datetime.utcnow()
start_time = datetime.now(UTC).replace(tzinfo=None)
expiry_time = start_time + timedelta(hours=1)
blob_service = BlobServiceClient(
account_url=f"https://{account_name}.blob.core.windows.net",
+23 -13
View File
@@ -10,6 +10,7 @@ import sys
import tqdm
import urllib.parse
import warnings
import zstd
from collections.abc import Callable, Iterable, Iterator
from urllib.parse import parse_qs, urlparse
@@ -34,8 +35,8 @@ class _LogFileReader:
ext = None
if not dat:
_, ext = os.path.splitext(urllib.parse.urlparse(fn).path)
if ext not in ('', '.bz2'):
# old rlogs weren't bz2 compressed
if ext not in ('', '.bz2', '.zst'):
# old rlogs weren't compressed
raise Exception(f"unknown extension {ext}")
with FileReader(fn) as f:
@@ -43,18 +44,21 @@ class _LogFileReader:
if ext == ".bz2" or dat.startswith(b'BZh9'):
dat = bz2.decompress(dat)
elif ext == ".zst" or dat.startswith(b'\x28\xB5\x2F\xFD'):
# https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#zstandard-frames
dat = zstd.decompress(dat)
ents = capnp_log.Event.read_multiple_bytes(dat)
_ents = []
self._ents = []
try:
for e in ents:
_ents.append(e)
self._ents.append(e)
except capnp.KjException:
warnings.warn("Corrupted events detected", RuntimeWarning, stacklevel=1)
self._ents = list(sorted(_ents, key=lambda x: x.logMonoTime) if sort_by_time else _ents)
self._ts = [x.logMonoTime for x in self._ents]
if sort_by_time:
self._ents.sort(key=lambda x: x.logMonoTime)
def __iter__(self) -> Iterator[capnp._DynamicStructReader]:
for ent in self._ents:
@@ -126,12 +130,12 @@ def comma_api_source(sr: SegmentRange, mode: ReadMode) -> LogPaths:
return apply_strategy(mode, rlog_paths, qlog_paths, valid_file=valid_file)
def internal_source(sr: SegmentRange, mode: ReadMode) -> LogPaths:
def internal_source(sr: SegmentRange, mode: ReadMode, file_ext: str = "bz2") -> LogPaths:
if not internal_source_available():
raise InternalUnavailableException
def get_internal_url(sr: SegmentRange, seg, file):
return f"cd:/{sr.dongle_id}/{sr.timestamp}/{seg}/{file}.bz2"
return f"cd:/{sr.dongle_id}/{sr.log_id}/{seg}/{file}.{file_ext}"
rlog_paths = [get_internal_url(sr, seg, "rlog") for seg in sr.seg_idxs]
qlog_paths = [get_internal_url(sr, seg, "qlog") for seg in sr.seg_idxs]
@@ -139,6 +143,10 @@ def internal_source(sr: SegmentRange, mode: ReadMode) -> LogPaths:
return apply_strategy(mode, rlog_paths, qlog_paths)
def internal_source_zst(sr: SegmentRange, mode: ReadMode, file_ext: str = "zst") -> LogPaths:
return internal_source(sr, mode, file_ext)
def openpilotci_source(sr: SegmentRange, mode: ReadMode) -> LogPaths:
rlog_paths = [get_url(sr.route_name, seg, "rlog") for seg in sr.seg_idxs]
qlog_paths = [get_url(sr.route_name, seg, "qlog") for seg in sr.seg_idxs]
@@ -162,7 +170,8 @@ def get_invalid_files(files):
def check_source(source: Source, *args) -> LogPaths:
files = source(*args)
assert next(get_invalid_files(files), False) is False
assert len(files) > 0, "No files on source"
assert next(get_invalid_files(files), False) is False, "Some files are invalid"
return files
@@ -170,8 +179,8 @@ def auto_source(sr: SegmentRange, mode=ReadMode.RLOG) -> LogPaths:
if mode == ReadMode.SANITIZED:
return comma_car_segments_source(sr, mode)
SOURCES: list[Source] = [internal_source, openpilotci_source, comma_api_source, comma_car_segments_source,]
exceptions = []
SOURCES: list[Source] = [internal_source, internal_source_zst, openpilotci_source, comma_api_source, comma_car_segments_source,]
exceptions = {}
# for automatic fallback modes, auto_source needs to first check if rlogs exist for any source
if mode in [ReadMode.AUTO, ReadMode.AUTO_INTERACTIVE]:
@@ -186,9 +195,10 @@ def auto_source(sr: SegmentRange, mode=ReadMode.RLOG) -> LogPaths:
try:
return check_source(source, sr, mode)
except Exception as e:
exceptions.append(e)
exceptions[source.__name__] = e
raise Exception(f"auto_source could not find any valid source, exceptions for sources: {exceptions}")
raise Exception("auto_source could not find any valid source, exceptions for sources:\n - " +
"\n - ".join([f"{k}: {repr(v)}" for k, v in exceptions.items()]))
def parse_useradmin(identifier: str):
+1 -5
View File
@@ -9,7 +9,7 @@ from openpilot.tools.lib.auth_config import get_token
from openpilot.tools.lib.api import CommaApi
from openpilot.tools.lib.helpers import RE
QLOG_FILENAMES = ['qlog', 'qlog.bz2']
QLOG_FILENAMES = ['qlog', 'qlog.bz2', 'qlog.zst']
QCAMERA_FILENAMES = ['qcamera.ts']
LOG_FILENAMES = ['rlog', 'rlog.bz2', 'raw_log.bz2']
CAMERA_FILENAMES = ['fcamera.hevc', 'video.hevc']
@@ -260,10 +260,6 @@ class SegmentRange:
def dongle_id(self) -> str:
return self.m.group("dongle_id")
@property
def timestamp(self) -> str:
return self.m.group("timestamp")
@property
def log_id(self) -> str:
return self.m.group("log_id")
-1
View File
@@ -158,7 +158,6 @@ def ui_thread(addr):
# TODO brake is deprecated
plot_arr[-1, name_to_arr_idx['computer_brake']] = clip(-sm['carControl'].actuators.accel/4.0, 0.0, 1.0)
plot_arr[-1, name_to_arr_idx['v_ego']] = sm['carState'].vEgo
plot_arr[-1, name_to_arr_idx['v_pid']] = sm['controlsState'].vPid
plot_arr[-1, name_to_arr_idx['v_cruise']] = sm['carState'].cruiseState.speed
plot_arr[-1, name_to_arr_idx['a_ego']] = sm['carState'].aEgo