mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-07-12 22:22:07 +08:00
Merge branch 'SP-157-sync-20240614' into SP-157-sync-priv-20240614
This commit is contained in:
@@ -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') &&
|
||||
|
||||
@@ -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
@@ -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 +0,0 @@
|
||||
3.11.4
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -1,11 +1,6 @@
|
||||
# What is cereal? [](https://github.com/commaai/cereal/actions) [](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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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()
|
||||
@@ -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
@@ -1 +1 @@
|
||||
#define COMMA_VERSION "0.9.7.1"
|
||||
#define COMMA_VERSION "0.9.8.0"
|
||||
|
||||
+4
-4
@@ -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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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>||
|
||||
|
||||
+1
-1
Submodule msgq_repo updated: 381fc3d9df...3fe8b7b121
Generated
+1526
-1482
File diff suppressed because one or more lines are too long
+38
-34
@@ -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 = "*"
|
||||
|
||||
@@ -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.
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.]
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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]))
|
||||
],
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 @@
|
||||
e536df5586a71b22baa789dc584d7eab67f1fbbb
|
||||
8737e368e17f859291164286feb4246e00c0b4a5
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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\"")
|
||||
|
||||
@@ -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
@@ -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():
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user