mirror of https://github.com/1okko/openpilot.git
Sync: `sunnypilot/sunnypilot:master` into `sunnypilot/openpilot-special:master-priv`
This commit is contained in:
commit
c55d11a865
|
@ -26,7 +26,9 @@ env:
|
|||
jobs:
|
||||
build_release:
|
||||
name: build release
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
|
||||
((github.event_name != 'pull_request') ||
|
||||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-latest' }}
|
||||
env:
|
||||
STRIPPED_DIR: /tmp/releasepilot
|
||||
steps:
|
||||
|
@ -116,6 +118,8 @@ jobs:
|
|||
submodules: true
|
||||
- uses: ./.github/workflows/setup-pre-commit
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
- name: Build openpilot
|
||||
run: ${{ env.RUN }} "scons -j$(nproc)"
|
||||
- name: pre-commit
|
||||
timeout-minutes: 4
|
||||
run: ${{ env.RUN }} "unset PYTHONWARNINGS && pre-commit run --all && chmod -R 777 /tmp/pre-commit"
|
||||
|
@ -143,7 +147,7 @@ jobs:
|
|||
$PYTEST --timeout 60 -m 'not slow' && \
|
||||
./selfdrive/ui/tests/create_test_translations.sh && \
|
||||
QT_QPA_PLATFORM=offscreen ./selfdrive/ui/tests/test_translations && \
|
||||
./selfdrive/ui/tests/test_translations.py"
|
||||
pytest ./selfdrive/ui/tests/test_translations.py"
|
||||
- name: "Upload coverage to Codecov"
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
|
|
|
@ -20,25 +20,6 @@ env:
|
|||
|
||||
|
||||
jobs:
|
||||
simulator_build:
|
||||
name: simulator docker build
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'commaai/openpilot'
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
- name: Setup to push to repo
|
||||
if: github.ref == 'refs/heads/master' && github.repository == 'commaai/openpilot'
|
||||
run: |
|
||||
echo "PUSH_IMAGE=true" >> "$GITHUB_ENV"
|
||||
$DOCKER_LOGIN
|
||||
- name: Build and push sim image
|
||||
run: |
|
||||
selfdrive/test/docker_build.sh sim
|
||||
|
||||
simulator_driving:
|
||||
name: simulator driving
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -47,7 +28,6 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- run: git lfs pull
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
- name: Build openpilot
|
||||
run: |
|
||||
|
|
|
@ -40,8 +40,9 @@ compile_commands.json
|
|||
compare_runtime*.html
|
||||
|
||||
persist
|
||||
board/obj/
|
||||
selfdrive/boardd/boardd
|
||||
selfdrive/pandad/pandad
|
||||
cereal/services.h
|
||||
cereal/gen
|
||||
selfdrive/logcatd/logcatd
|
||||
selfdrive/mapd/default_speeds_by_region.json
|
||||
system/proclogd/proclogd
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
[submodule "opendbc"]
|
||||
path = opendbc
|
||||
url = https://github.com/sunnyhaibin/opendbc.git
|
||||
[submodule "cereal"]
|
||||
path = cereal
|
||||
url = https://github.com/sunnyhaibin/cereal.git
|
||||
[submodule "msgq"]
|
||||
path = msgq_repo
|
||||
url = https://github.com/commaai/msgq.git
|
||||
[submodule "rednose_repo"]
|
||||
path = rednose_repo
|
||||
url = https://github.com/commaai/rednose.git
|
||||
|
|
|
@ -24,19 +24,19 @@ repos:
|
|||
- --maxkb=120
|
||||
- --enforce-all
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.2.6
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude: '^(third_party/)|(body/)|(cereal/)|(panda/)|(opendbc/)|(rednose/)|(rednose_repo/)|(teleoprtc/)|(teleoprtc_repo/)|(selfdrive/ui/translations/.*.ts)|(poetry.lock)'
|
||||
exclude: '^(third_party/)|(body/)|(msgq/)|(panda/)|(opendbc/)|(rednose/)|(rednose_repo/)|(teleoprtc/)|(teleoprtc_repo/)|(selfdrive/ui/translations/.*.ts)|(poetry.lock)'
|
||||
args:
|
||||
# if you've got a short variable name that's getting flagged, add it here
|
||||
- -L bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints
|
||||
- -L bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn
|
||||
- --builtins clear,rare,informal,usage,code,names,en-GB_to_en-US
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.4.4
|
||||
rev: v0.4.8
|
||||
hooks:
|
||||
- id: ruff
|
||||
exclude: '^(third_party/)|(cereal/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)'
|
||||
exclude: '^(third_party/)|(msgq/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)'
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: mypy
|
||||
|
@ -47,7 +47,7 @@ repos:
|
|||
args:
|
||||
- --local-partial-types
|
||||
- --explicit-package-bases
|
||||
exclude: '^(third_party/)|(body/)|(cereal/)|(opendbc/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)'
|
||||
exclude: '^(third_party/)|(body/)|(msgq/)|(opendbc/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)'
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: cppcheck
|
||||
|
@ -55,7 +55,7 @@ repos:
|
|||
entry: cppcheck
|
||||
language: system
|
||||
types: [c++]
|
||||
exclude: '^(third_party/)|(cereal/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(tools/)|(selfdrive/modeld/thneed/debug/)|(selfdrive/modeld/test/)|(selfdrive/camerad/test/)|(installer/)'
|
||||
exclude: '^(third_party/)|(msgq/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(tools/)|(selfdrive/modeld/thneed/debug/)|(selfdrive/modeld/test/)|(selfdrive/camerad/test/)|(installer/)'
|
||||
args:
|
||||
- --error-exitcode=1
|
||||
- --language=c++
|
||||
|
@ -66,7 +66,7 @@ repos:
|
|||
rev: 1.6.1
|
||||
hooks:
|
||||
- id: cpplint
|
||||
exclude: '^(third_party/)|(cereal/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(generated/)'
|
||||
exclude: '^(third_party/)|(msgq/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(generated/)'
|
||||
args:
|
||||
- --quiet
|
||||
- --counting=total
|
||||
|
@ -78,7 +78,7 @@ repos:
|
|||
rev: v0.16.2
|
||||
hooks:
|
||||
- id: cython-lint
|
||||
exclude: '^(third_party/)|(cereal/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(generated/)'
|
||||
exclude: '^(third_party/)|(msgq/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(generated/)'
|
||||
args:
|
||||
- --max-line-length=240
|
||||
- --ignore=E111, E302, E305
|
||||
|
@ -86,8 +86,8 @@ repos:
|
|||
hooks:
|
||||
- id: test_translations
|
||||
name: test translations
|
||||
entry: selfdrive/ui/tests/test_translations.py
|
||||
language: script
|
||||
entry: pytest selfdrive/ui/tests/test_translations.py
|
||||
language: system
|
||||
pass_filenames: false
|
||||
files: '^selfdrive/ui/translations/'
|
||||
- repo: https://github.com/python-poetry/poetry
|
||||
|
@ -98,6 +98,6 @@ repos:
|
|||
args:
|
||||
- --lock
|
||||
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||
rev: 0.28.3
|
||||
rev: 0.28.4
|
||||
hooks:
|
||||
- id: check-github-workflows
|
||||
|
|
|
@ -20,6 +20,8 @@ COPY ./release ${OPENPILOT_PATH}/release
|
|||
COPY ./common ${OPENPILOT_PATH}/common
|
||||
COPY ./opendbc ${OPENPILOT_PATH}/opendbc
|
||||
COPY ./cereal ${OPENPILOT_PATH}/cereal
|
||||
COPY ./msgq_repo ${OPENPILOT_PATH}/msgq_repo
|
||||
COPY ./msgq ${OPENPILOT_PATH}/msgq
|
||||
COPY ./panda ${OPENPILOT_PATH}/panda
|
||||
COPY ./selfdrive ${OPENPILOT_PATH}/selfdrive
|
||||
COPY ./system ${OPENPILOT_PATH}/system
|
||||
|
|
|
@ -192,7 +192,7 @@ node {
|
|||
'HW + Unit Tests': {
|
||||
deviceStage("tici-hardware", "tici-common", ["UNSAFE=1"], [
|
||||
["build", "cd system/manager && ./build.py"],
|
||||
["test pandad", "pytest selfdrive/boardd/tests/test_pandad.py"],
|
||||
["test pandad", "pytest selfdrive/pandad/tests/test_pandad.py"],
|
||||
["test power draw", "pytest -s system/hardware/tici/tests/test_power_draw.py"],
|
||||
["test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py"],
|
||||
["test pigeond", "pytest system/ubloxd/tests/test_pigeond.py"],
|
||||
|
@ -202,7 +202,7 @@ node {
|
|||
'loopback': {
|
||||
deviceStage("loopback", "tici-loopback", ["UNSAFE=1"], [
|
||||
["build openpilot", "cd system/manager && ./build.py"],
|
||||
["test boardd loopback", "pytest selfdrive/boardd/tests/test_boardd_loopback.py"],
|
||||
["test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"],
|
||||
])
|
||||
},
|
||||
'camerad': {
|
||||
|
@ -236,9 +236,9 @@ node {
|
|||
'tizi': {
|
||||
deviceStage("tizi", "tizi", ["UNSAFE=1"], [
|
||||
["build openpilot", "cd system/manager && ./build.py"],
|
||||
["test boardd loopback", "SINGLE_PANDA=1 pytest selfdrive/boardd/tests/test_boardd_loopback.py"],
|
||||
["test boardd spi", "pytest selfdrive/boardd/tests/test_boardd_spi.py"],
|
||||
["test pandad", "pytest selfdrive/boardd/tests/test_pandad.py"],
|
||||
["test pandad loopback", "SINGLE_PANDA=1 pytest selfdrive/pandad/tests/test_pandad_loopback.py"],
|
||||
["test pandad spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"],
|
||||
["test pandad", "pytest selfdrive/pandad/tests/test_pandad.py"],
|
||||
["test amp", "pytest system/hardware/tici/tests/test_amplifier.py"],
|
||||
["test hw", "pytest system/hardware/tici/tests/test_hardware.py"],
|
||||
["test qcomgpsd", "pytest system/qcomgpsd/tests/test_qcomgpsd.py"],
|
||||
|
|
13
RELEASES.md
13
RELEASES.md
|
@ -1,6 +1,13 @@
|
|||
Version 0.9.8 (2024-XX-XX)
|
||||
========================
|
||||
* Always on driver monitoring toggle
|
||||
|
||||
Version 0.9.7 (2024-06-11)
|
||||
========================
|
||||
* 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
|
||||
* 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
|
||||
|
@ -634,7 +641,7 @@ Version 0.5.13 (2019-05-31)
|
|||
* Reduce CPU utilization by 20% and improve stability
|
||||
* Temporarily remove mapd functionalities to improve stability
|
||||
* Add openpilot record-only mode for unsupported cars
|
||||
* Synchronize controlsd to boardd to reduce latency
|
||||
* Synchronize controlsd to pandad to reduce latency
|
||||
* Remove panda support for Subaru giraffe
|
||||
|
||||
Version 0.5.12 (2019-05-16)
|
||||
|
@ -970,7 +977,7 @@ Version 0.2.8 (2017-02-27)
|
|||
Version 0.2.7 (2017-02-08)
|
||||
===========================
|
||||
* Better performance and pictures at night
|
||||
* Fix ptr alignment issue in boardd
|
||||
* Fix ptr alignment issue in pandad
|
||||
* Fix brake error light, fix crash if too cold
|
||||
|
||||
Version 0.2.6 (2017-01-31)
|
||||
|
@ -1002,7 +1009,7 @@ Version 0.2.2 (2017-01-10)
|
|||
Version 0.2.1 (2016-12-14)
|
||||
===========================
|
||||
* Performance improvements, removal of more numpy
|
||||
* Fix boardd process priority
|
||||
* Fix pandad process priority
|
||||
* Make counter timer reset on use of steering wheel
|
||||
|
||||
Version 0.2 (2016-12-12)
|
||||
|
|
15
SConstruct
15
SConstruct
|
@ -67,7 +67,7 @@ AddOption('--pc-thneed',
|
|||
AddOption('--minimal',
|
||||
action='store_false',
|
||||
dest='extras',
|
||||
default=os.path.islink(Dir('#rednose/').abspath), # minimal by default on release branch (where rednose is not a link)
|
||||
default=os.path.exists(File('#.lfsconfig').abspath), # minimal by default on release branch (where there's no LFS)
|
||||
help='the minimum build to run openpilot. no tests, tools, etc.')
|
||||
|
||||
## Architecture name breakdown (arch)
|
||||
|
@ -209,6 +209,7 @@ env = Environment(
|
|||
"#third_party/qrcode",
|
||||
"#third_party",
|
||||
"#cereal",
|
||||
"#msgq",
|
||||
"#opendbc/can",
|
||||
"#third_party/maplibre-native-qt/include",
|
||||
f"#third_party/maplibre-native-qt/{arch}/include"
|
||||
|
@ -223,10 +224,9 @@ env = Environment(
|
|||
CFLAGS=["-std=gnu11"] + cflags,
|
||||
CXXFLAGS=["-std=c++1z"] + cxxflags,
|
||||
LIBPATH=libpath + [
|
||||
"#cereal",
|
||||
"#msgq_repo",
|
||||
"#third_party",
|
||||
"#opendbc/can",
|
||||
"#selfdrive/boardd",
|
||||
"#selfdrive/pandad",
|
||||
"#common",
|
||||
"#rednose/helpers",
|
||||
],
|
||||
|
@ -357,8 +357,13 @@ gpucommon = [_gpucommon]
|
|||
|
||||
Export('common', 'gpucommon')
|
||||
|
||||
# Build cereal and messaging
|
||||
# Build messaging (cereal + msgq + socketmaster + their dependencies)
|
||||
SConscript(['msgq_repo/SConscript'])
|
||||
SConscript(['cereal/SConscript'])
|
||||
Import('socketmaster', 'msgq')
|
||||
messaging = [socketmaster, msgq, 'zmq', 'capnp', 'kj',]
|
||||
Export('messaging')
|
||||
|
||||
|
||||
# Build other submodules
|
||||
SConscript([
|
||||
|
|
1
cereal
1
cereal
|
@ -1 +0,0 @@
|
|||
Subproject commit bda2b7a4a2e3a9de3dddf8ea8ddbc890d9e7a3ea
|
|
@ -0,0 +1,60 @@
|
|||
# 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)
|
||||
|
||||
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
|
||||
|
||||
|
||||
## Messaging Spec
|
||||
|
||||
You'll find the message types in [log.capnp](log.capnp). It uses [Cap'n proto](https://capnproto.org/capnp-tool.html) and defines one struct called `Event`.
|
||||
|
||||
All `Events` have a `logMonoTime` and a `valid`. Then a big union defines the packet type.
|
||||
|
||||
### Best Practices
|
||||
|
||||
- **All fields must describe quantities in SI units**, unless otherwise specified in the field name.
|
||||
- In the context of the message they are in, field names should be completely unambiguous.
|
||||
- All values should be easy to plot and be human-readable with minimal parsing.
|
||||
|
||||
### Maintaining backwards-compatibility
|
||||
|
||||
When making changes to the messaging spec you want to maintain backwards-compatibility, such that old logs can
|
||||
be parsed with a new version of cereal. Adding structs and adding members to structs is generally safe, most other
|
||||
things are not. Read more details [here](https://capnproto.org/language.html).
|
||||
|
||||
### Custom forks
|
||||
|
||||
Forks of [openpilot](https://github.com/commaai/openpilot) might want to add things to the messaging
|
||||
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.
|
||||
|
||||
Example
|
||||
---
|
||||
```python
|
||||
import cereal.messaging as messaging
|
||||
|
||||
# in subscriber
|
||||
sm = messaging.SubMaster(['sensorEvents'])
|
||||
while 1:
|
||||
sm.update()
|
||||
print(sm['sensorEvents'])
|
||||
|
||||
```
|
||||
|
||||
```python
|
||||
# in publisher
|
||||
pm = messaging.PubMaster(['sensorEvents'])
|
||||
dat = messaging.new_message('sensorEvents', size=1)
|
||||
dat.sensorEvents[0] = {"gyro": {"v": [0.1, -0.1, 0.1]}}
|
||||
pm.send('sensorEvents', dat)
|
||||
```
|
|
@ -0,0 +1,31 @@
|
|||
Import('env', 'envCython', 'arch', 'common', 'msgq')
|
||||
|
||||
import shutil
|
||||
|
||||
cereal_dir = Dir('.')
|
||||
gen_dir = Dir('gen')
|
||||
other_dir = Dir('#msgq')
|
||||
|
||||
# Build cereal
|
||||
schema_files = ['log.capnp', 'car.capnp', 'legacy.capnp', 'custom.capnp']
|
||||
env.Command(["gen/c/include/c++.capnp.h"], [], "mkdir -p " + gen_dir.path + "/c/include && touch $TARGETS")
|
||||
env.Command([f'gen/cpp/{s}.c++' for s in schema_files] + [f'gen/cpp/{s}.h' for s in schema_files],
|
||||
schema_files,
|
||||
f"capnpc --src-prefix={cereal_dir.path} $SOURCES -o c++:{gen_dir.path}/cpp/")
|
||||
|
||||
# TODO: remove non shared cereal and messaging
|
||||
cereal_objects = env.SharedObject([f'gen/cpp/{s}.c++' for s in schema_files])
|
||||
|
||||
cereal = env.Library('cereal', cereal_objects)
|
||||
env.SharedLibrary('cereal_shared', cereal_objects)
|
||||
|
||||
# Build messaging
|
||||
|
||||
services_h = env.Command(['services.h'], ['services.py'], 'python3 ' + cereal_dir.path + '/services.py > $TARGET')
|
||||
env.Program('messaging/bridge', ['messaging/bridge.cc'], LIBS=[msgq, 'zmq', common])
|
||||
|
||||
|
||||
socketmaster = env.SharedObject(['messaging/socketmaster.cc'])
|
||||
socketmaster = env.Library('socketmaster', socketmaster)
|
||||
|
||||
Export('cereal', 'socketmaster')
|
|
@ -0,0 +1,9 @@
|
|||
import os
|
||||
import capnp
|
||||
|
||||
CEREAL_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||
capnp.remove_import_hook()
|
||||
|
||||
log = capnp.load(os.path.join(CEREAL_PATH, "log.capnp"))
|
||||
car = capnp.load(os.path.join(CEREAL_PATH, "car.capnp"))
|
||||
custom = capnp.load(os.path.join(CEREAL_PATH, "custom.capnp"))
|
|
@ -0,0 +1,757 @@
|
|||
using Cxx = import "./include/c++.capnp";
|
||||
$Cxx.namespace("cereal");
|
||||
|
||||
@0x8e2af1e708af8b8d;
|
||||
|
||||
# ******* events causing controls state machine transition *******
|
||||
|
||||
struct CarEvent @0x9b1657f34caf3ad3 {
|
||||
name @0 :EventName;
|
||||
|
||||
# event types
|
||||
enable @1 :Bool;
|
||||
noEntry @2 :Bool;
|
||||
warning @3 :Bool; # alerts presented only when enabled or soft disabling
|
||||
userDisable @4 :Bool;
|
||||
softDisable @5 :Bool;
|
||||
immediateDisable @6 :Bool;
|
||||
preEnable @7 :Bool;
|
||||
permanent @8 :Bool; # alerts presented regardless of openpilot state
|
||||
overrideLateral @10 :Bool;
|
||||
overrideLongitudinal @9 :Bool;
|
||||
|
||||
enum EventName @0xbaa8c5d505f727de {
|
||||
canError @0;
|
||||
steerUnavailable @1;
|
||||
wrongGear @4;
|
||||
doorOpen @5;
|
||||
seatbeltNotLatched @6;
|
||||
espDisabled @7;
|
||||
wrongCarMode @8;
|
||||
steerTempUnavailable @9;
|
||||
reverseGear @10;
|
||||
buttonCancel @11;
|
||||
buttonEnable @12;
|
||||
pedalPressed @13; # exits active state
|
||||
preEnableStandstill @73; # added during pre-enable state with brake
|
||||
gasPressedOverride @108; # added when user is pressing gas with no disengage on gas
|
||||
steerOverride @114;
|
||||
cruiseDisabled @14;
|
||||
speedTooLow @17;
|
||||
outOfSpace @18;
|
||||
overheat @19;
|
||||
calibrationIncomplete @20;
|
||||
calibrationInvalid @21;
|
||||
calibrationRecalibrating @117;
|
||||
controlsMismatch @22;
|
||||
pcmEnable @23;
|
||||
pcmDisable @24;
|
||||
radarFault @26;
|
||||
brakeHold @28;
|
||||
parkBrake @29;
|
||||
manualRestart @30;
|
||||
lowSpeedLockout @31;
|
||||
joystickDebug @34;
|
||||
steerTempUnavailableSilent @35;
|
||||
resumeRequired @36;
|
||||
preDriverDistracted @37;
|
||||
promptDriverDistracted @38;
|
||||
driverDistracted @39;
|
||||
preDriverUnresponsive @43;
|
||||
promptDriverUnresponsive @44;
|
||||
driverUnresponsive @45;
|
||||
belowSteerSpeed @46;
|
||||
lowBattery @48;
|
||||
accFaulted @51;
|
||||
sensorDataInvalid @52;
|
||||
commIssue @53;
|
||||
commIssueAvgFreq @109;
|
||||
tooDistracted @54;
|
||||
posenetInvalid @55;
|
||||
soundsUnavailable @56;
|
||||
preLaneChangeLeft @57;
|
||||
preLaneChangeRight @58;
|
||||
laneChange @59;
|
||||
lowMemory @63;
|
||||
stockAeb @64;
|
||||
ldw @65;
|
||||
carUnrecognized @66;
|
||||
invalidLkasSetting @69;
|
||||
speedTooHigh @70;
|
||||
laneChangeBlocked @71;
|
||||
relayMalfunction @72;
|
||||
stockFcw @74;
|
||||
startup @75;
|
||||
startupNoCar @76;
|
||||
startupNoControl @77;
|
||||
startupMaster @78;
|
||||
startupNoFw @104;
|
||||
fcw @79;
|
||||
steerSaturated @80;
|
||||
belowEngageSpeed @84;
|
||||
noGps @85;
|
||||
wrongCruiseMode @87;
|
||||
modeldLagging @89;
|
||||
deviceFalling @90;
|
||||
fanMalfunction @91;
|
||||
cameraMalfunction @92;
|
||||
cameraFrameRate @110;
|
||||
processNotRunning @95;
|
||||
dashcamMode @96;
|
||||
controlsInitializing @98;
|
||||
usbError @99;
|
||||
roadCameraError @100;
|
||||
driverCameraError @101;
|
||||
wideRoadCameraError @102;
|
||||
highCpuUsage @105;
|
||||
cruiseMismatch @106;
|
||||
lkasDisabled @107;
|
||||
canBusMissing @111;
|
||||
controlsdLagging @112;
|
||||
resumeBlocked @113;
|
||||
steerTimeLimit @115;
|
||||
vehicleSensorsInvalid @116;
|
||||
locationdTemporaryError @103;
|
||||
locationdPermanentError @118;
|
||||
paramsdTemporaryError @50;
|
||||
paramsdPermanentError @119;
|
||||
actuatorsApiUnavailable @120;
|
||||
manualSteeringRequired @121;
|
||||
manualLongitudinalRequired @122;
|
||||
silentPedalPressed @123;
|
||||
silentButtonEnable @124;
|
||||
silentBrakeHold @125;
|
||||
silentWrongGear @126;
|
||||
spReverseGear @127;
|
||||
preKeepHandsOnWheel @128;
|
||||
promptKeepHandsOnWheel @129;
|
||||
keepHandsOnWheel @130;
|
||||
speedLimitActive @131;
|
||||
speedLimitValueChange @132;
|
||||
e2eLongStop @133;
|
||||
e2eLongStart @134;
|
||||
controlsMismatchLong @135;
|
||||
cruiseEngageBlocked @136;
|
||||
laneChangeRoadEdge @137;
|
||||
speedLimitPreActive @138;
|
||||
speedLimitConfirmed @139;
|
||||
torqueNNLoad @140;
|
||||
|
||||
radarCanErrorDEPRECATED @15;
|
||||
communityFeatureDisallowedDEPRECATED @62;
|
||||
radarCommIssueDEPRECATED @67;
|
||||
driverMonitorLowAccDEPRECATED @68;
|
||||
gasUnavailableDEPRECATED @3;
|
||||
dataNeededDEPRECATED @16;
|
||||
modelCommIssueDEPRECATED @27;
|
||||
ipasOverrideDEPRECATED @33;
|
||||
geofenceDEPRECATED @40;
|
||||
driverMonitorOnDEPRECATED @41;
|
||||
driverMonitorOffDEPRECATED @42;
|
||||
calibrationProgressDEPRECATED @47;
|
||||
invalidGiraffeHondaDEPRECATED @49;
|
||||
invalidGiraffeToyotaDEPRECATED @60;
|
||||
internetConnectivityNeededDEPRECATED @61;
|
||||
whitePandaUnsupportedDEPRECATED @81;
|
||||
commIssueWarningDEPRECATED @83;
|
||||
focusRecoverActiveDEPRECATED @86;
|
||||
neosUpdateRequiredDEPRECATED @88;
|
||||
modelLagWarningDEPRECATED @93;
|
||||
startupOneplusDEPRECATED @82;
|
||||
startupFuzzyFingerprintDEPRECATED @97;
|
||||
noTargetDEPRECATED @25;
|
||||
brakeUnavailableDEPRECATED @2;
|
||||
plannerErrorDEPRECATED @32;
|
||||
gpsMalfunctionDEPRECATED @94;
|
||||
}
|
||||
}
|
||||
|
||||
# ******* main car state @ 100hz *******
|
||||
# all speeds in m/s
|
||||
|
||||
struct CarState {
|
||||
events @13 :List(CarEvent);
|
||||
|
||||
# CAN health
|
||||
canValid @26 :Bool; # invalid counter/checksums
|
||||
canTimeout @40 :Bool; # CAN bus dropped out
|
||||
canErrorCounter @48 :UInt32;
|
||||
|
||||
# car speed
|
||||
vEgo @1 :Float32; # best estimate of speed
|
||||
aEgo @16 :Float32; # best estimate of acceleration
|
||||
vEgoRaw @17 :Float32; # unfiltered speed from CAN sensors
|
||||
vEgoCluster @44 :Float32; # best estimate of speed shown on car's instrument cluster, used for UI
|
||||
|
||||
yawRate @22 :Float32; # best estimate of yaw rate
|
||||
standstill @18 :Bool;
|
||||
wheelSpeeds @2 :WheelSpeeds;
|
||||
|
||||
# gas pedal, 0.0-1.0
|
||||
gas @3 :Float32; # this is user pedal only
|
||||
gasPressed @4 :Bool; # this is user pedal only
|
||||
|
||||
engineRpm @46 :Float32;
|
||||
|
||||
# brake pedal, 0.0-1.0
|
||||
brake @5 :Float32; # this is user pedal only
|
||||
brakePressed @6 :Bool; # this is user pedal only
|
||||
regenBraking @45 :Bool; # this is user pedal only
|
||||
parkingBrake @39 :Bool;
|
||||
brakeHoldActive @38 :Bool;
|
||||
|
||||
# steering wheel
|
||||
steeringAngleDeg @7 :Float32;
|
||||
steeringAngleOffsetDeg @37 :Float32; # Offset betweens sensors in case there multiple
|
||||
steeringRateDeg @15 :Float32;
|
||||
steeringTorque @8 :Float32; # TODO: standardize units
|
||||
steeringTorqueEps @27 :Float32; # TODO: standardize units
|
||||
steeringPressed @9 :Bool; # if the user is using the steering wheel
|
||||
steerFaultTemporary @35 :Bool; # temporary EPS fault
|
||||
steerFaultPermanent @36 :Bool; # permanent EPS fault
|
||||
stockAeb @30 :Bool;
|
||||
stockFcw @31 :Bool;
|
||||
espDisabled @32 :Bool;
|
||||
accFaulted @42 :Bool;
|
||||
carFaultedNonCritical @47 :Bool; # some ECU is faulted, but car remains controllable
|
||||
|
||||
# cruise state
|
||||
cruiseState @10 :CruiseState;
|
||||
|
||||
# gear
|
||||
gearShifter @14 :GearShifter;
|
||||
|
||||
# button presses
|
||||
buttonEvents @11 :List(ButtonEvent);
|
||||
leftBlinker @20 :Bool;
|
||||
rightBlinker @21 :Bool;
|
||||
genericToggle @23 :Bool;
|
||||
|
||||
# lock info
|
||||
doorOpen @24 :Bool;
|
||||
seatbeltUnlatched @25 :Bool;
|
||||
|
||||
# clutch (manual transmission only)
|
||||
clutchPressed @28 :Bool;
|
||||
|
||||
madsEnabled @51 :Bool;
|
||||
leftBlinkerOn @52 :Bool;
|
||||
rightBlinkerOn @53 :Bool;
|
||||
disengageByBrake @54 :Bool;
|
||||
belowLaneChangeSpeed @55 :Bool;
|
||||
accEnabled @56 :Bool;
|
||||
latActive @57 :Bool;
|
||||
gapAdjustCruiseTr @58 :Int32;
|
||||
endToEndLong @59 :Bool;
|
||||
customStockLong @60 :CustomStockLong;
|
||||
|
||||
struct CustomStockLong {
|
||||
cruiseButton @0 :Int16;
|
||||
finalSpeedKph @1 :Float32;
|
||||
vCruiseKphPrev @2 :Float32;
|
||||
targetSpeed @3 :Float32;
|
||||
vSetDis @4 :Float32;
|
||||
speedDiff @5 :Float32;
|
||||
buttonType @6 :Int16;
|
||||
}
|
||||
|
||||
# blindspot sensors
|
||||
leftBlindspot @33 :Bool; # Is there something blocking the left lane change
|
||||
rightBlindspot @34 :Bool; # Is there something blocking the right lane change
|
||||
|
||||
fuelGauge @41 :Float32; # battery or fuel tank level from 0.0 to 1.0
|
||||
charging @43 :Bool;
|
||||
|
||||
# process meta
|
||||
cumLagMs @50 :Float32;
|
||||
|
||||
struct WheelSpeeds {
|
||||
# optional wheel speeds
|
||||
fl @0 :Float32;
|
||||
fr @1 :Float32;
|
||||
rl @2 :Float32;
|
||||
rr @3 :Float32;
|
||||
}
|
||||
|
||||
struct CruiseState {
|
||||
enabled @0 :Bool;
|
||||
speed @1 :Float32;
|
||||
speedCluster @6 :Float32; # Set speed as shown on instrument cluster
|
||||
available @2 :Bool;
|
||||
speedOffset @3 :Float32;
|
||||
standstill @4 :Bool;
|
||||
nonAdaptive @5 :Bool;
|
||||
speedLimit @7 :Float32;
|
||||
}
|
||||
|
||||
enum GearShifter {
|
||||
unknown @0;
|
||||
park @1;
|
||||
drive @2;
|
||||
neutral @3;
|
||||
reverse @4;
|
||||
sport @5;
|
||||
low @6;
|
||||
brake @7;
|
||||
eco @8;
|
||||
manumatic @9;
|
||||
}
|
||||
|
||||
# send on change
|
||||
struct ButtonEvent {
|
||||
pressed @0 :Bool;
|
||||
type @1 :Type;
|
||||
|
||||
enum Type {
|
||||
unknown @0;
|
||||
leftBlinker @1;
|
||||
rightBlinker @2;
|
||||
accelCruise @3;
|
||||
decelCruise @4;
|
||||
cancel @5;
|
||||
altButton1 @6;
|
||||
altButton2 @7;
|
||||
altButton3 @8;
|
||||
setCruise @9;
|
||||
resumeCruise @10;
|
||||
gapAdjustCruise @11;
|
||||
}
|
||||
}
|
||||
|
||||
# deprecated
|
||||
errorsDEPRECATED @0 :List(CarEvent.EventName);
|
||||
brakeLightsDEPRECATED @19 :Bool;
|
||||
steeringRateLimitedDEPRECATED @29 :Bool;
|
||||
canMonoTimesDEPRECATED @12: List(UInt64);
|
||||
canRcvTimeoutDEPRECATED @49 :Bool;
|
||||
}
|
||||
|
||||
# ******* radar state @ 20hz *******
|
||||
|
||||
struct RadarData @0x888ad6581cf0aacb {
|
||||
errors @0 :List(Error);
|
||||
points @1 :List(RadarPoint);
|
||||
|
||||
enum Error {
|
||||
canError @0;
|
||||
fault @1;
|
||||
wrongConfig @2;
|
||||
}
|
||||
|
||||
# similar to LiveTracks
|
||||
# is one timestamp valid for all? I think so
|
||||
struct RadarPoint {
|
||||
trackId @0 :UInt64; # no trackId reuse
|
||||
|
||||
# these 3 are the minimum required
|
||||
dRel @1 :Float32; # m from the front bumper of the car
|
||||
yRel @2 :Float32; # m
|
||||
vRel @3 :Float32; # m/s
|
||||
|
||||
# these are optional and valid if they are not NaN
|
||||
aRel @4 :Float32; # m/s^2
|
||||
yvRel @5 :Float32; # m/s
|
||||
|
||||
# some radars flag measurements VS estimates
|
||||
measured @6 :Bool;
|
||||
}
|
||||
|
||||
# deprecated
|
||||
canMonoTimesDEPRECATED @2 :List(UInt64);
|
||||
}
|
||||
|
||||
# ******* car controls @ 100hz *******
|
||||
|
||||
struct CarControl {
|
||||
# must be true for any actuator commands to work
|
||||
enabled @0 :Bool;
|
||||
latActive @11: Bool;
|
||||
longActive @12: Bool;
|
||||
vCruise @17 :Float32; # actual set speed
|
||||
|
||||
# Actuator commands as computed by controlsd
|
||||
actuators @6 :Actuators;
|
||||
|
||||
# moved to CarOutput
|
||||
actuatorsOutputDEPRECATED @10 :Actuators;
|
||||
|
||||
leftBlinker @15: Bool;
|
||||
rightBlinker @16: Bool;
|
||||
|
||||
orientationNED @13 :List(Float32);
|
||||
angularVelocity @14 :List(Float32);
|
||||
|
||||
cruiseControl @4 :CruiseControl;
|
||||
hudControl @5 :HUDControl;
|
||||
|
||||
struct Actuators {
|
||||
# range from 0.0 - 1.0
|
||||
gas @0: Float32;
|
||||
brake @1: Float32;
|
||||
# range from -1.0 - 1.0
|
||||
steer @2: Float32;
|
||||
# value sent over can to the car
|
||||
steerOutputCan @8: Float32;
|
||||
steeringAngleDeg @3: Float32;
|
||||
|
||||
curvature @7: Float32;
|
||||
|
||||
speed @6: Float32; # m/s
|
||||
accel @4: Float32; # m/s^2
|
||||
longControlState @5: LongControlState;
|
||||
|
||||
enum LongControlState @0xe40f3a917d908282{
|
||||
off @0;
|
||||
pid @1;
|
||||
stopping @2;
|
||||
starting @3;
|
||||
}
|
||||
}
|
||||
|
||||
struct CruiseControl {
|
||||
cancel @0: Bool;
|
||||
resume @1: Bool;
|
||||
override @4: Bool;
|
||||
speedOverrideDEPRECATED @2: Float32;
|
||||
accelOverrideDEPRECATED @3: Float32;
|
||||
}
|
||||
|
||||
struct HUDControl {
|
||||
speedVisible @0: Bool;
|
||||
setSpeed @1: Float32;
|
||||
lanesVisible @2: Bool;
|
||||
leadVisible @3: Bool;
|
||||
visualAlert @4: VisualAlert;
|
||||
audibleAlert @5: AudibleAlert;
|
||||
rightLaneVisible @6: Bool;
|
||||
leftLaneVisible @7: Bool;
|
||||
rightLaneDepart @8: Bool;
|
||||
leftLaneDepart @9: Bool;
|
||||
leadDistanceBars @10: Int8; # 1-3: 1 is closest, 3 is farthest. some ports may utilize 2-4 bars instead
|
||||
|
||||
enum VisualAlert {
|
||||
# these are the choices from the Honda
|
||||
# map as good as you can for your car
|
||||
none @0;
|
||||
fcw @1;
|
||||
steerRequired @2;
|
||||
brakePressed @3;
|
||||
wrongGear @4;
|
||||
seatbeltUnbuckled @5;
|
||||
speedTooHigh @6;
|
||||
ldw @7;
|
||||
}
|
||||
|
||||
enum AudibleAlert {
|
||||
none @0;
|
||||
|
||||
engage @1;
|
||||
disengage @2;
|
||||
refuse @3;
|
||||
|
||||
warningSoft @4;
|
||||
warningImmediate @5;
|
||||
|
||||
prompt @6;
|
||||
promptRepeat @7;
|
||||
promptDistracted @8;
|
||||
promptStarting @9;
|
||||
promptSingleLow @10;
|
||||
promptSingleHigh @11;
|
||||
}
|
||||
}
|
||||
|
||||
gasDEPRECATED @1 :Float32;
|
||||
brakeDEPRECATED @2 :Float32;
|
||||
steeringTorqueDEPRECATED @3 :Float32;
|
||||
activeDEPRECATED @7 :Bool;
|
||||
rollDEPRECATED @8 :Float32;
|
||||
pitchDEPRECATED @9 :Float32;
|
||||
}
|
||||
|
||||
struct CarOutput {
|
||||
# Any car specific rate limits or quirks applied by
|
||||
# the CarController are reflected in actuatorsOutput
|
||||
# and matches what is sent to the car
|
||||
actuatorsOutput @0 :CarControl.Actuators;
|
||||
}
|
||||
|
||||
# ****** car param ******
|
||||
|
||||
struct CarParams {
|
||||
carName @0 :Text;
|
||||
carFingerprint @1 :Text;
|
||||
fuzzyFingerprint @55 :Bool;
|
||||
|
||||
notCar @66 :Bool; # flag for non-car robotics platforms
|
||||
|
||||
pcmCruise @3 :Bool; # is openpilot's state tied to the PCM's cruise state?
|
||||
enableDsu @5 :Bool; # driving support unit
|
||||
enableBsm @56 :Bool; # blind spot monitoring
|
||||
flags @64 :UInt32; # flags for car specific quirks
|
||||
experimentalLongitudinalAvailable @71 :Bool;
|
||||
pcmCruiseSpeed @74 :Bool; # is openpilot's state tied to the PCM's cruise speed?
|
||||
customStockLongAvailable @75 :Bool;
|
||||
spFlags @76 :UInt32; # flags for car specific quirks in sunnypilot
|
||||
|
||||
minEnableSpeed @7 :Float32;
|
||||
minSteerSpeed @8 :Float32;
|
||||
safetyConfigs @62 :List(SafetyConfig);
|
||||
alternativeExperience @65 :Int16; # panda flag for features like no disengage on gas
|
||||
|
||||
# Car docs fields
|
||||
maxLateralAccel @68 :Float32;
|
||||
autoResumeSng @69 :Bool; # describes whether car can resume from a stop automatically
|
||||
|
||||
# things about the car in the manual
|
||||
mass @17 :Float32; # [kg] curb weight: all fluids no cargo
|
||||
wheelbase @18 :Float32; # [m] distance from rear axle to front axle
|
||||
centerToFront @19 :Float32; # [m] distance from center of mass to front axle
|
||||
steerRatio @20 :Float32; # [] ratio of steering wheel angle to front wheel angle
|
||||
steerRatioRear @21 :Float32; # [] ratio of steering wheel angle to rear wheel angle (usually 0)
|
||||
|
||||
# things we can derive
|
||||
rotationalInertia @22 :Float32; # [kg*m2] body rotational inertia
|
||||
tireStiffnessFactor @72 :Float32; # scaling factor used in calculating tireStiffness[Front,Rear]
|
||||
tireStiffnessFront @23 :Float32; # [N/rad] front tire coeff of stiff
|
||||
tireStiffnessRear @24 :Float32; # [N/rad] rear tire coeff of stiff
|
||||
|
||||
longitudinalTuning @25 :LongitudinalPIDTuning;
|
||||
lateralParams @48 :LateralParams;
|
||||
lateralTuning :union {
|
||||
pid @26 :LateralPIDTuning;
|
||||
indiDEPRECATED @27 :LateralINDITuning;
|
||||
lqrDEPRECATED @40 :LateralLQRTuning;
|
||||
torque @67 :LateralTorqueTuning;
|
||||
}
|
||||
|
||||
steerLimitAlert @28 :Bool;
|
||||
steerLimitTimer @47 :Float32; # time before steerLimitAlert is issued
|
||||
|
||||
vEgoStopping @29 :Float32; # Speed at which the car goes into stopping state
|
||||
vEgoStarting @59 :Float32; # Speed at which the car goes into starting state
|
||||
stoppingControl @31 :Bool; # Does the car allow full control even at lows speeds when stopping
|
||||
steerControlType @34 :SteerControlType;
|
||||
radarUnavailable @35 :Bool; # True when radar objects aren't visible on CAN or aren't parsed out
|
||||
stopAccel @60 :Float32; # Required acceleration to keep vehicle stationary
|
||||
stoppingDecelRate @52 :Float32; # m/s^2/s while trying to stop
|
||||
startAccel @32 :Float32; # Required acceleration to get car moving
|
||||
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
|
||||
openpilotLongitudinalControl @37 :Bool; # is openpilot doing the longitudinal control?
|
||||
carVin @38 :Text; # VIN number queried during fingerprinting
|
||||
dashcamOnly @41: Bool;
|
||||
passive @73: Bool; # is openpilot in control?
|
||||
transmissionType @43 :TransmissionType;
|
||||
carFw @44 :List(CarFw);
|
||||
|
||||
radarTimeStep @45: Float32 = 0.05; # time delta between radar updates, 20Hz is very standard
|
||||
fingerprintSource @49: FingerprintSource;
|
||||
networkLocation @50 :NetworkLocation; # Where Panda/C2 is integrated into the car's CAN network
|
||||
|
||||
wheelSpeedFactor @63 :Float32; # Multiplier on wheels speeds to computer actual speeds
|
||||
|
||||
struct SafetyConfig {
|
||||
safetyModel @0 :SafetyModel;
|
||||
safetyParam @3 :UInt16;
|
||||
safetyParamDEPRECATED @1 :Int16;
|
||||
safetyParam2DEPRECATED @2 :UInt32;
|
||||
}
|
||||
|
||||
struct LateralParams {
|
||||
torqueBP @0 :List(Int32);
|
||||
torqueV @1 :List(Int32);
|
||||
}
|
||||
|
||||
struct LateralPIDTuning {
|
||||
kpBP @0 :List(Float32);
|
||||
kpV @1 :List(Float32);
|
||||
kiBP @2 :List(Float32);
|
||||
kiV @3 :List(Float32);
|
||||
kf @4 :Float32;
|
||||
}
|
||||
|
||||
struct LateralTorqueTuning {
|
||||
useSteeringAngle @0 :Bool;
|
||||
kp @1 :Float32;
|
||||
ki @2 :Float32;
|
||||
friction @3 :Float32;
|
||||
kf @4 :Float32;
|
||||
steeringAngleDeadzoneDeg @5 :Float32;
|
||||
latAccelFactor @6 :Float32;
|
||||
latAccelOffset @7 :Float32;
|
||||
nnModelName @8 :Text;
|
||||
nnModelFuzzyMatch @9 :Bool;
|
||||
}
|
||||
|
||||
struct LongitudinalPIDTuning {
|
||||
kpBP @0 :List(Float32);
|
||||
kpV @1 :List(Float32);
|
||||
kiBP @2 :List(Float32);
|
||||
kiV @3 :List(Float32);
|
||||
kf @6 :Float32;
|
||||
deadzoneBP @4 :List(Float32);
|
||||
deadzoneV @5 :List(Float32);
|
||||
}
|
||||
|
||||
struct LateralINDITuning {
|
||||
outerLoopGainBP @4 :List(Float32);
|
||||
outerLoopGainV @5 :List(Float32);
|
||||
innerLoopGainBP @6 :List(Float32);
|
||||
innerLoopGainV @7 :List(Float32);
|
||||
timeConstantBP @8 :List(Float32);
|
||||
timeConstantV @9 :List(Float32);
|
||||
actuatorEffectivenessBP @10 :List(Float32);
|
||||
actuatorEffectivenessV @11 :List(Float32);
|
||||
|
||||
outerLoopGainDEPRECATED @0 :Float32;
|
||||
innerLoopGainDEPRECATED @1 :Float32;
|
||||
timeConstantDEPRECATED @2 :Float32;
|
||||
actuatorEffectivenessDEPRECATED @3 :Float32;
|
||||
}
|
||||
|
||||
struct LateralLQRTuning {
|
||||
scale @0 :Float32;
|
||||
ki @1 :Float32;
|
||||
dcGain @2 :Float32;
|
||||
|
||||
# State space system
|
||||
a @3 :List(Float32);
|
||||
b @4 :List(Float32);
|
||||
c @5 :List(Float32);
|
||||
|
||||
k @6 :List(Float32); # LQR gain
|
||||
l @7 :List(Float32); # Kalman gain
|
||||
}
|
||||
|
||||
enum SafetyModel {
|
||||
silent @0;
|
||||
hondaNidec @1;
|
||||
toyota @2;
|
||||
elm327 @3;
|
||||
gm @4;
|
||||
hondaBoschGiraffe @5;
|
||||
ford @6;
|
||||
cadillac @7;
|
||||
hyundai @8;
|
||||
chrysler @9;
|
||||
tesla @10;
|
||||
subaru @11;
|
||||
gmPassive @12;
|
||||
mazda @13;
|
||||
nissan @14;
|
||||
volkswagen @15;
|
||||
toyotaIpas @16;
|
||||
allOutput @17;
|
||||
gmAscm @18;
|
||||
noOutput @19; # like silent but without silent CAN TXs
|
||||
hondaBosch @20;
|
||||
volkswagenPq @21;
|
||||
subaruPreglobal @22; # pre-Global platform
|
||||
hyundaiLegacy @23;
|
||||
hyundaiCommunity @24;
|
||||
volkswagenMlb @25;
|
||||
hongqi @26;
|
||||
body @27;
|
||||
hyundaiCanfd @28;
|
||||
volkswagenMqbEvo @29;
|
||||
chryslerCusw @30;
|
||||
psa @31;
|
||||
}
|
||||
|
||||
enum SteerControlType {
|
||||
torque @0;
|
||||
angle @1;
|
||||
|
||||
curvatureDEPRECATED @2;
|
||||
}
|
||||
|
||||
enum TransmissionType {
|
||||
unknown @0;
|
||||
automatic @1; # Traditional auto, including DSG
|
||||
manual @2; # True "stick shift" only
|
||||
direct @3; # Electric vehicle or other direct drive
|
||||
cvt @4;
|
||||
}
|
||||
|
||||
struct CarFw {
|
||||
ecu @0 :Ecu;
|
||||
fwVersion @1 :Data;
|
||||
address @2 :UInt32;
|
||||
subAddress @3 :UInt8;
|
||||
responseAddress @4 :UInt32;
|
||||
request @5 :List(Data);
|
||||
brand @6 :Text;
|
||||
bus @7 :UInt8;
|
||||
logging @8 :Bool;
|
||||
obdMultiplexing @9 :Bool;
|
||||
}
|
||||
|
||||
enum Ecu {
|
||||
eps @0;
|
||||
abs @1;
|
||||
fwdRadar @2;
|
||||
fwdCamera @3;
|
||||
engine @4;
|
||||
unknown @5;
|
||||
transmission @8; # Transmission Control Module
|
||||
hybrid @18; # hybrid control unit, e.g. Chrysler's HCP, Honda's IMA Control Unit, Toyota's hybrid control computer
|
||||
srs @9; # airbag
|
||||
gateway @10; # can gateway
|
||||
hud @11; # heads up display
|
||||
combinationMeter @12; # instrument cluster
|
||||
electricBrakeBooster @15;
|
||||
shiftByWire @16;
|
||||
adas @19;
|
||||
cornerRadar @21;
|
||||
hvac @20;
|
||||
parkingAdas @7; # parking assist system ECU, e.g. Toyota's IPAS, Hyundai's RSPA, etc.
|
||||
epb @22; # electronic parking brake
|
||||
telematics @23;
|
||||
body @24; # body control module
|
||||
|
||||
# Toyota only
|
||||
dsu @6;
|
||||
|
||||
# Honda only
|
||||
vsa @13; # Vehicle Stability Assist
|
||||
programmedFuelInjection @14;
|
||||
|
||||
debug @17;
|
||||
}
|
||||
|
||||
enum FingerprintSource {
|
||||
can @0;
|
||||
fw @1;
|
||||
fixed @2;
|
||||
}
|
||||
|
||||
enum NetworkLocation {
|
||||
fwdCamera @0; # Standard/default integration at LKAS camera
|
||||
gateway @1; # Integration at vehicle's CAN gateway
|
||||
}
|
||||
|
||||
enableGasInterceptorDEPRECATED @2 :Bool;
|
||||
enableCameraDEPRECATED @4 :Bool;
|
||||
enableApgsDEPRECATED @6 :Bool;
|
||||
steerRateCostDEPRECATED @33 :Float32;
|
||||
isPandaBlackDEPRECATED @39 :Bool;
|
||||
hasStockCameraDEPRECATED @57 :Bool;
|
||||
safetyParamDEPRECATED @10 :Int16;
|
||||
safetyModelDEPRECATED @9 :SafetyModel;
|
||||
safetyModelPassiveDEPRECATED @42 :SafetyModel = silent;
|
||||
minSpeedCanDEPRECATED @51 :Float32;
|
||||
communityFeatureDEPRECATED @46: Bool;
|
||||
startingAccelRateDEPRECATED @53 :Float32;
|
||||
steerMaxBPDEPRECATED @11 :List(Float32);
|
||||
steerMaxVDEPRECATED @12 :List(Float32);
|
||||
gasMaxBPDEPRECATED @13 :List(Float32);
|
||||
gasMaxVDEPRECATED @14 :List(Float32);
|
||||
brakeMaxBPDEPRECATED @15 :List(Float32);
|
||||
brakeMaxVDEPRECATED @16 :List(Float32);
|
||||
directAccelControlDEPRECATED @30 :Bool;
|
||||
maxSteeringAngleDegDEPRECATED @54 :Float32;
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
using Cxx = import "./include/c++.capnp";
|
||||
$Cxx.namespace("cereal");
|
||||
|
||||
using Car = import "car.capnp";
|
||||
|
||||
@0xb526ba661d550a59;
|
||||
|
||||
# custom.capnp: a home for empty structs reserved for custom forks
|
||||
# These structs are guaranteed to remain reserved and empty in mainline
|
||||
# cereal, so use these if you want custom events in your fork.
|
||||
|
||||
# you can rename the struct, but don't change the identifier
|
||||
|
||||
enum LongitudinalPersonalitySP {
|
||||
aggressive @0;
|
||||
moderate @1;
|
||||
standard @2;
|
||||
relaxed @3;
|
||||
}
|
||||
|
||||
struct ControlsStateSP @0x81c2f05a394cf4af {
|
||||
lateralState @0 :Text;
|
||||
personality @8 :LongitudinalPersonalitySP;
|
||||
|
||||
lateralControlState :union {
|
||||
indiState @1 :LateralINDIState;
|
||||
pidState @2 :LateralPIDState;
|
||||
angleState @3 :LateralAngleState;
|
||||
debugState @4 :LateralDebugState;
|
||||
torqueState @5 :LateralTorqueState;
|
||||
curvatureState @6 :LateralCurvatureState;
|
||||
|
||||
lqrStateDEPRECATED @7 :LateralLQRState;
|
||||
}
|
||||
|
||||
struct LateralINDIState {
|
||||
}
|
||||
|
||||
struct LateralPIDState {
|
||||
}
|
||||
|
||||
struct LateralAngleState {
|
||||
}
|
||||
|
||||
struct LateralDebugState {
|
||||
}
|
||||
|
||||
struct LateralTorqueState {
|
||||
nnLog @0 :List(Float32);
|
||||
}
|
||||
|
||||
struct LateralCurvatureState {
|
||||
}
|
||||
|
||||
struct LateralLQRState {
|
||||
}
|
||||
}
|
||||
|
||||
struct LongitudinalPlanSP @0xaedffd8f31e7b55d {
|
||||
visionTurnControllerState @0 :VisionTurnControllerState;
|
||||
visionTurnSpeed @1 :Float32;
|
||||
visionCurrentLatAcc @16 :Float32;
|
||||
visionMaxPredLatAcc @17 :Float32;
|
||||
|
||||
speedLimitControlState @2 :SpeedLimitControlState;
|
||||
speedLimit @3 :Float32;
|
||||
speedLimitOffset @4 :Float32;
|
||||
distToSpeedLimit @5 :Float32;
|
||||
isMapSpeedLimit @6 :Bool;
|
||||
speedLimitPercOffset @11 :Bool;
|
||||
speedLimitValueOffset @12 :Float32;
|
||||
desiredTF @13 :Float32;
|
||||
notSpeedLimit @14 :Int16;
|
||||
e2eX @15 :List(Float32);
|
||||
e2eBlended @18 :Text;
|
||||
e2eStatus @22 :Bool;
|
||||
|
||||
distToTurn @7 :Float32;
|
||||
turnSpeed @8 :Float32;
|
||||
turnSpeedControlState @9 :SpeedLimitControlState;
|
||||
turnSign @10 :Int16;
|
||||
|
||||
events @19 :List(Car.CarEvent);
|
||||
longitudinalPlanSource @20 :LongitudinalPlanSource;
|
||||
|
||||
personalityDEPRECATED @21 :LongitudinalPersonalitySP;
|
||||
|
||||
enum SpeedLimitControlState {
|
||||
inactive @0; # No speed limit set or not enabled by parameter.
|
||||
tempInactive @1; # User wants to ignore speed limit until it changes.
|
||||
adapting @2; # Reducing speed to match new speed limit.
|
||||
active @3; # Cruising at speed limit.
|
||||
preActive @4;
|
||||
}
|
||||
|
||||
enum VisionTurnControllerState {
|
||||
disabled @0; # No predicted substantial turn on vision range or feature disabled.
|
||||
entering @1; # A substantial turn is predicted ahead, adapting speed to turn comfort levels.
|
||||
turning @2; # Actively turning. Managing acceleration to provide a roll on turn feeling.
|
||||
leaving @3; # Road ahead straightens. Start to allow positive acceleration.
|
||||
}
|
||||
|
||||
enum LongitudinalPlanSource {
|
||||
cruise @0;
|
||||
lead0 @1;
|
||||
lead1 @2;
|
||||
lead2 @3;
|
||||
e2e @4;
|
||||
turn @5;
|
||||
limit @6;
|
||||
turnlimit @7;
|
||||
}
|
||||
}
|
||||
|
||||
struct LateralPlanSP @0xf35cc4560bbf6ec2 {
|
||||
laneWidth @0 :Float32;
|
||||
lProb @1 :Float32;
|
||||
rProb @2 :Float32;
|
||||
|
||||
dProb @3 :Float32;
|
||||
|
||||
dynamicLaneProfile @4 :Int8;
|
||||
standstillElapsed @5 :Float32;
|
||||
dynamicLaneProfileStatus @9 :Bool;
|
||||
|
||||
dPathWLinesXDEPRECATED @6 :List(Float32);
|
||||
dPathWLinesYDEPRECATED @7 :List(Float32);
|
||||
laneChangePrevDEPRECATED @8 :Bool;
|
||||
laneChangeEdgeBlockDEPRECATED @10 :Bool;
|
||||
}
|
||||
|
||||
struct DriverMonitoringStateSP @0xda96579883444c35 {
|
||||
handsOnWheelState @0 :HandsOnWheelState;
|
||||
notModified @1 :Float32;
|
||||
|
||||
enum HandsOnWheelState {
|
||||
none @0; # hand on wheel monitoring inactive
|
||||
ok @1; # driver has hands on steering wheel
|
||||
minor @2; # hands off steering wheel for acceptable period
|
||||
warning @3; # hands off steering wheel for warning period
|
||||
critical @4; # # hands off steering wheel for critical period
|
||||
terminal @5; # # hands off steering wheel for terminal period
|
||||
}
|
||||
}
|
||||
|
||||
struct LiveMapDataSP @0x80ae746ee2596b11 {
|
||||
speedLimitValid @0 :Bool;
|
||||
speedLimit @1 :Float32;
|
||||
speedLimitAheadValid @2 :Bool;
|
||||
speedLimitAhead @3 :Float32;
|
||||
speedLimitAheadDistance @4 :Float32;
|
||||
turnSpeedLimitValid @5 :Bool;
|
||||
turnSpeedLimit @6 :Float32;
|
||||
turnSpeedLimitEndDistance @7 :Float32;
|
||||
turnSpeedLimitSign @8 :Int16;
|
||||
turnSpeedLimitsAhead @9 :List(Float32);
|
||||
turnSpeedLimitsAheadDistances @10 :List(Float32);
|
||||
turnSpeedLimitsAheadSigns @11 :List(Int16);
|
||||
lastGpsTimestamp @12 :Int64; # Milliseconds since January 1, 1970.
|
||||
currentRoadName @13 :Text;
|
||||
lastGpsLatitude @14 :Float64;
|
||||
lastGpsLongitude @15 :Float64;
|
||||
lastGpsSpeed @16 :Float32;
|
||||
lastGpsBearingDeg @17 :Float32;
|
||||
lastGpsAccuracy @18 :Float32;
|
||||
lastGpsBearingAccuracyDeg @19 :Float32;
|
||||
dataType @20 :DataType;
|
||||
|
||||
enum DataType {
|
||||
default @0;
|
||||
offline @1;
|
||||
online @2;
|
||||
}
|
||||
}
|
||||
|
||||
struct E2eLongStateSP @0xa5cd762cd951a455 {
|
||||
status @0 :UInt16;
|
||||
}
|
||||
|
||||
struct ModelDataV2SP @0xf98d843bfd7004a3 {
|
||||
laneChangePrev @0 :Bool;
|
||||
laneChangeEdgeBlock @1 :Bool;
|
||||
}
|
||||
|
||||
struct CustomReserved7 @0xb86e6369214c01c8 {
|
||||
}
|
||||
|
||||
struct CustomReserved8 @0xf416ec09499d9d19 {
|
||||
}
|
||||
|
||||
struct CustomReserved9 @0xa1680744031fdb2d {
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
# Licensed under the MIT License:
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
@0xbdf87d7bb8304e81;
|
||||
$namespace("capnp::annotations");
|
||||
|
||||
annotation namespace(file): Text;
|
||||
annotation name(field, enumerant, struct, enum, interface, method, param, group, union): Text;
|
|
@ -0,0 +1,574 @@
|
|||
using Cxx = import "./include/c++.capnp";
|
||||
$Cxx.namespace("cereal");
|
||||
|
||||
@0x80ef1ec4889c2a63;
|
||||
|
||||
# legacy.capnp: a home for deprecated structs
|
||||
|
||||
struct LogRotate @0x9811e1f38f62f2d1 {
|
||||
segmentNum @0 :Int32;
|
||||
path @1 :Text;
|
||||
}
|
||||
|
||||
struct LiveUI @0xc08240f996aefced {
|
||||
rearViewCam @0 :Bool;
|
||||
alertText1 @1 :Text;
|
||||
alertText2 @2 :Text;
|
||||
awarenessStatus @3 :Float32;
|
||||
}
|
||||
|
||||
struct UiLayoutState @0x88dcce08ad29dda0 {
|
||||
activeApp @0 :App;
|
||||
sidebarCollapsed @1 :Bool;
|
||||
mapEnabled @2 :Bool;
|
||||
mockEngaged @3 :Bool;
|
||||
|
||||
enum App @0x9917470acf94d285 {
|
||||
home @0;
|
||||
music @1;
|
||||
nav @2;
|
||||
settings @3;
|
||||
none @4;
|
||||
}
|
||||
}
|
||||
|
||||
struct OrbslamCorrection @0x8afd33dc9b35e1aa {
|
||||
correctionMonoTime @0 :UInt64;
|
||||
prePositionECEF @1 :List(Float64);
|
||||
postPositionECEF @2 :List(Float64);
|
||||
prePoseQuatECEF @3 :List(Float32);
|
||||
postPoseQuatECEF @4 :List(Float32);
|
||||
numInliers @5 :UInt32;
|
||||
}
|
||||
|
||||
struct EthernetPacket @0xa99a9d5b33cf5859 {
|
||||
pkt @0 :Data;
|
||||
ts @1 :Float32;
|
||||
}
|
||||
|
||||
struct CellInfo @0xcff7566681c277ce {
|
||||
timestamp @0 :UInt64;
|
||||
repr @1 :Text; # android toString() for now
|
||||
}
|
||||
|
||||
struct WifiScan @0xd4df5a192382ba0b {
|
||||
bssid @0 :Text;
|
||||
ssid @1 :Text;
|
||||
capabilities @2 :Text;
|
||||
frequency @3 :Int32;
|
||||
level @4 :Int32;
|
||||
timestamp @5 :Int64;
|
||||
|
||||
centerFreq0 @6 :Int32;
|
||||
centerFreq1 @7 :Int32;
|
||||
channelWidth @8 :ChannelWidth;
|
||||
operatorFriendlyName @9 :Text;
|
||||
venueName @10 :Text;
|
||||
is80211mcResponder @11 :Bool;
|
||||
passpoint @12 :Bool;
|
||||
|
||||
distanceCm @13 :Int32;
|
||||
distanceSdCm @14 :Int32;
|
||||
|
||||
enum ChannelWidth @0xcb6a279f015f6b51 {
|
||||
w20Mhz @0;
|
||||
w40Mhz @1;
|
||||
w80Mhz @2;
|
||||
w160Mhz @3;
|
||||
w80Plus80Mhz @4;
|
||||
}
|
||||
}
|
||||
|
||||
struct LiveEventData @0x94b7baa90c5c321e {
|
||||
name @0 :Text;
|
||||
value @1 :Int32;
|
||||
}
|
||||
|
||||
struct ModelData @0xb8aad62cffef28a9 {
|
||||
frameId @0 :UInt32;
|
||||
frameAge @12 :UInt32;
|
||||
frameDropPerc @13 :Float32;
|
||||
timestampEof @9 :UInt64;
|
||||
modelExecutionTime @14 :Float32;
|
||||
gpuExecutionTime @16 :Float32;
|
||||
rawPred @15 :Data;
|
||||
|
||||
path @1 :PathData;
|
||||
leftLane @2 :PathData;
|
||||
rightLane @3 :PathData;
|
||||
lead @4 :LeadData;
|
||||
freePath @6 :List(Float32);
|
||||
|
||||
settings @5 :ModelSettings;
|
||||
leadFuture @7 :LeadData;
|
||||
speed @8 :List(Float32);
|
||||
meta @10 :MetaData;
|
||||
longitudinal @11 :LongitudinalData;
|
||||
|
||||
struct PathData @0x8817eeea389e9f08 {
|
||||
points @0 :List(Float32);
|
||||
prob @1 :Float32;
|
||||
std @2 :Float32;
|
||||
stds @3 :List(Float32);
|
||||
poly @4 :List(Float32);
|
||||
validLen @5 :Float32;
|
||||
}
|
||||
|
||||
struct LeadData @0xd1c9bef96d26fa91 {
|
||||
dist @0 :Float32;
|
||||
prob @1 :Float32;
|
||||
std @2 :Float32;
|
||||
relVel @3 :Float32;
|
||||
relVelStd @4 :Float32;
|
||||
relY @5 :Float32;
|
||||
relYStd @6 :Float32;
|
||||
relA @7 :Float32;
|
||||
relAStd @8 :Float32;
|
||||
}
|
||||
|
||||
struct ModelSettings @0xa26e3710efd3e914 {
|
||||
bigBoxX @0 :UInt16;
|
||||
bigBoxY @1 :UInt16;
|
||||
bigBoxWidth @2 :UInt16;
|
||||
bigBoxHeight @3 :UInt16;
|
||||
boxProjection @4 :List(Float32);
|
||||
yuvCorrection @5 :List(Float32);
|
||||
inputTransform @6 :List(Float32);
|
||||
}
|
||||
|
||||
struct MetaData @0x9744f25fb60f2bf8 {
|
||||
engagedProb @0 :Float32;
|
||||
desirePrediction @1 :List(Float32);
|
||||
brakeDisengageProb @2 :Float32;
|
||||
gasDisengageProb @3 :Float32;
|
||||
steerOverrideProb @4 :Float32;
|
||||
desireState @5 :List(Float32);
|
||||
}
|
||||
|
||||
struct LongitudinalData @0xf98f999c6a071122 {
|
||||
distances @2 :List(Float32);
|
||||
speeds @0 :List(Float32);
|
||||
accelerations @1 :List(Float32);
|
||||
}
|
||||
}
|
||||
|
||||
struct ECEFPoint @0xc25bbbd524983447 {
|
||||
x @0 :Float64;
|
||||
y @1 :Float64;
|
||||
z @2 :Float64;
|
||||
}
|
||||
|
||||
struct ECEFPointDEPRECATED @0xe10e21168db0c7f7 {
|
||||
x @0 :Float32;
|
||||
y @1 :Float32;
|
||||
z @2 :Float32;
|
||||
}
|
||||
|
||||
struct GPSPlannerPoints @0xab54c59699f8f9f3 {
|
||||
curPosDEPRECATED @0 :ECEFPointDEPRECATED;
|
||||
pointsDEPRECATED @1 :List(ECEFPointDEPRECATED);
|
||||
curPos @6 :ECEFPoint;
|
||||
points @7 :List(ECEFPoint);
|
||||
valid @2 :Bool;
|
||||
trackName @3 :Text;
|
||||
speedLimit @4 :Float32;
|
||||
accelTarget @5 :Float32;
|
||||
}
|
||||
|
||||
struct GPSPlannerPlan @0xf5ad1d90cdc1dd6b {
|
||||
valid @0 :Bool;
|
||||
poly @1 :List(Float32);
|
||||
trackName @2 :Text;
|
||||
speed @3 :Float32;
|
||||
acceleration @4 :Float32;
|
||||
pointsDEPRECATED @5 :List(ECEFPointDEPRECATED);
|
||||
points @6 :List(ECEFPoint);
|
||||
xLookahead @7 :Float32;
|
||||
}
|
||||
|
||||
struct UiNavigationEvent @0x90c8426c3eaddd3b {
|
||||
type @0: Type;
|
||||
status @1: Status;
|
||||
distanceTo @2: Float32;
|
||||
endRoadPointDEPRECATED @3: ECEFPointDEPRECATED;
|
||||
endRoadPoint @4: ECEFPoint;
|
||||
|
||||
enum Type @0xe8db07dcf8fcea05 {
|
||||
none @0;
|
||||
laneChangeLeft @1;
|
||||
laneChangeRight @2;
|
||||
mergeLeft @3;
|
||||
mergeRight @4;
|
||||
turnLeft @5;
|
||||
turnRight @6;
|
||||
}
|
||||
|
||||
enum Status @0xb9aa88c75ef99a1f {
|
||||
none @0;
|
||||
passive @1;
|
||||
approaching @2;
|
||||
active @3;
|
||||
}
|
||||
}
|
||||
|
||||
struct LiveLocationData @0xb99b2bc7a57e8128 {
|
||||
status @0 :UInt8;
|
||||
|
||||
# 3D fix
|
||||
lat @1 :Float64;
|
||||
lon @2 :Float64;
|
||||
alt @3 :Float32; # m
|
||||
|
||||
# speed
|
||||
speed @4 :Float32; # m/s
|
||||
|
||||
# NED velocity components
|
||||
vNED @5 :List(Float32);
|
||||
|
||||
# roll, pitch, heading (x,y,z)
|
||||
roll @6 :Float32; # WRT to center of earth?
|
||||
pitch @7 :Float32; # WRT to center of earth?
|
||||
heading @8 :Float32; # WRT to north?
|
||||
|
||||
# what are these?
|
||||
wanderAngle @9 :Float32;
|
||||
trackAngle @10 :Float32;
|
||||
|
||||
# car frame -- https://upload.wikimedia.org/wikipedia/commons/f/f5/RPY_angles_of_cars.png
|
||||
|
||||
# gyro, in car frame, deg/s
|
||||
gyro @11 :List(Float32);
|
||||
|
||||
# accel, in car frame, m/s^2
|
||||
accel @12 :List(Float32);
|
||||
|
||||
accuracy @13 :Accuracy;
|
||||
|
||||
source @14 :SensorSource;
|
||||
# if we are fixing a location in the past
|
||||
fixMonoTime @15 :UInt64;
|
||||
|
||||
gpsWeek @16 :Int32;
|
||||
timeOfWeek @17 :Float64;
|
||||
|
||||
positionECEF @18 :List(Float64);
|
||||
poseQuatECEF @19 :List(Float32);
|
||||
pitchCalibration @20 :Float32;
|
||||
yawCalibration @21 :Float32;
|
||||
imuFrame @22 :List(Float32);
|
||||
|
||||
struct Accuracy @0x943dc4625473b03f {
|
||||
pNEDError @0 :List(Float32);
|
||||
vNEDError @1 :List(Float32);
|
||||
rollError @2 :Float32;
|
||||
pitchError @3 :Float32;
|
||||
headingError @4 :Float32;
|
||||
ellipsoidSemiMajorError @5 :Float32;
|
||||
ellipsoidSemiMinorError @6 :Float32;
|
||||
ellipsoidOrientationError @7 :Float32;
|
||||
}
|
||||
|
||||
enum SensorSource @0xc871d3cc252af657 {
|
||||
applanix @0;
|
||||
kalman @1;
|
||||
orbslam @2;
|
||||
timing @3;
|
||||
dummy @4;
|
||||
}
|
||||
}
|
||||
|
||||
struct OrbOdometry @0xd7700859ed1f5b76 {
|
||||
# timing first
|
||||
startMonoTime @0 :UInt64;
|
||||
endMonoTime @1 :UInt64;
|
||||
|
||||
# fundamental matrix and error
|
||||
f @2: List(Float64);
|
||||
err @3: Float64;
|
||||
|
||||
# number of inlier points
|
||||
inliers @4: Int32;
|
||||
|
||||
# for debug only
|
||||
# indexed by endMonoTime features
|
||||
# value is startMonoTime feature match
|
||||
# -1 if no match
|
||||
matches @5: List(Int16);
|
||||
}
|
||||
|
||||
struct OrbFeatures @0xcd60164a8a0159ef {
|
||||
timestampEof @0 :UInt64;
|
||||
# transposed arrays of normalized image coordinates
|
||||
# len(xs) == len(ys) == len(descriptors) * 32
|
||||
xs @1 :List(Float32);
|
||||
ys @2 :List(Float32);
|
||||
descriptors @3 :Data;
|
||||
octaves @4 :List(Int8);
|
||||
|
||||
# match index to last OrbFeatures
|
||||
# -1 if no match
|
||||
timestampLastEof @5 :UInt64;
|
||||
matches @6: List(Int16);
|
||||
}
|
||||
|
||||
struct OrbFeaturesSummary @0xd500d30c5803fa4f {
|
||||
timestampEof @0 :UInt64;
|
||||
timestampLastEof @1 :UInt64;
|
||||
|
||||
featureCount @2 :UInt16;
|
||||
matchCount @3 :UInt16;
|
||||
computeNs @4 :UInt64;
|
||||
}
|
||||
|
||||
struct OrbKeyFrame @0xc8233c0345e27e24 {
|
||||
# this is a globally unique id for the KeyFrame
|
||||
id @0: UInt64;
|
||||
|
||||
# this is the location of the KeyFrame
|
||||
pos @1: ECEFPoint;
|
||||
|
||||
# these are the features in the world
|
||||
# len(dpos) == len(descriptors) * 32
|
||||
dpos @2 :List(ECEFPoint);
|
||||
descriptors @3 :Data;
|
||||
}
|
||||
|
||||
struct KalmanOdometry @0x92e21bb7ea38793a {
|
||||
trans @0 :List(Float32); # m/s in device frame
|
||||
rot @1 :List(Float32); # rad/s in device frame
|
||||
transStd @2 :List(Float32); # std m/s in device frame
|
||||
rotStd @3 :List(Float32); # std rad/s in device frame
|
||||
}
|
||||
|
||||
struct OrbObservation @0x9b326d4e436afec7 {
|
||||
observationMonoTime @0 :UInt64;
|
||||
normalizedCoordinates @1 :List(Float32);
|
||||
locationECEF @2 :List(Float64);
|
||||
matchDistance @3: UInt32;
|
||||
}
|
||||
|
||||
struct CalibrationFeatures @0x8fdfadb254ea867a {
|
||||
frameId @0 :UInt32;
|
||||
|
||||
p0 @1 :List(Float32);
|
||||
p1 @2 :List(Float32);
|
||||
status @3 :List(Int8);
|
||||
}
|
||||
|
||||
struct NavStatus @0xbd8822120928120c {
|
||||
isNavigating @0 :Bool;
|
||||
currentAddress @1 :Address;
|
||||
|
||||
struct Address @0xce7cd672cacc7814 {
|
||||
title @0 :Text;
|
||||
lat @1 :Float64;
|
||||
lng @2 :Float64;
|
||||
house @3 :Text;
|
||||
address @4 :Text;
|
||||
street @5 :Text;
|
||||
city @6 :Text;
|
||||
state @7 :Text;
|
||||
country @8 :Text;
|
||||
}
|
||||
}
|
||||
|
||||
struct NavUpdate @0xdb98be6565516acb {
|
||||
isNavigating @0 :Bool;
|
||||
curSegment @1 :Int32;
|
||||
segments @2 :List(Segment);
|
||||
|
||||
struct LatLng @0x9eaef9187cadbb9b {
|
||||
lat @0 :Float64;
|
||||
lng @1 :Float64;
|
||||
}
|
||||
|
||||
struct Segment @0xa5b39b4fc4d7da3f {
|
||||
from @0 :LatLng;
|
||||
to @1 :LatLng;
|
||||
updateTime @2 :Int32;
|
||||
distance @3 :Int32;
|
||||
crossTime @4 :Int32;
|
||||
exitNo @5 :Int32;
|
||||
instruction @6 :Instruction;
|
||||
|
||||
parts @7 :List(LatLng);
|
||||
|
||||
enum Instruction @0xc5417a637451246f {
|
||||
turnLeft @0;
|
||||
turnRight @1;
|
||||
keepLeft @2;
|
||||
keepRight @3;
|
||||
straight @4;
|
||||
roundaboutExitNumber @5;
|
||||
roundaboutExit @6;
|
||||
roundaboutTurnLeft @7;
|
||||
unkn8 @8;
|
||||
roundaboutStraight @9;
|
||||
unkn10 @10;
|
||||
roundaboutTurnRight @11;
|
||||
unkn12 @12;
|
||||
roundaboutUturn @13;
|
||||
unkn14 @14;
|
||||
arrive @15;
|
||||
exitLeft @16;
|
||||
exitRight @17;
|
||||
unkn18 @18;
|
||||
uturn @19;
|
||||
# ...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TrafficEvent @0xacfa74a094e62626 {
|
||||
type @0 :Type;
|
||||
distance @1 :Float32;
|
||||
action @2 :Action;
|
||||
resuming @3 :Bool;
|
||||
|
||||
enum Type @0xd85d75253435bf4b {
|
||||
stopSign @0;
|
||||
lightRed @1;
|
||||
lightYellow @2;
|
||||
lightGreen @3;
|
||||
stopLight @4;
|
||||
}
|
||||
|
||||
enum Action @0xa6f6ce72165ccb49 {
|
||||
none @0;
|
||||
yield @1;
|
||||
stop @2;
|
||||
resumeReady @3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct AndroidGnss @0xdfdf30d03fc485bd {
|
||||
union {
|
||||
measurements @0 :Measurements;
|
||||
navigationMessage @1 :NavigationMessage;
|
||||
}
|
||||
|
||||
struct Measurements @0xa20710d4f428d6cd {
|
||||
clock @0 :Clock;
|
||||
measurements @1 :List(Measurement);
|
||||
|
||||
struct Clock @0xa0e27b453a38f450 {
|
||||
timeNanos @0 :Int64;
|
||||
hardwareClockDiscontinuityCount @1 :Int32;
|
||||
|
||||
hasTimeUncertaintyNanos @2 :Bool;
|
||||
timeUncertaintyNanos @3 :Float64;
|
||||
|
||||
hasLeapSecond @4 :Bool;
|
||||
leapSecond @5 :Int32;
|
||||
|
||||
hasFullBiasNanos @6 :Bool;
|
||||
fullBiasNanos @7 :Int64;
|
||||
|
||||
hasBiasNanos @8 :Bool;
|
||||
biasNanos @9 :Float64;
|
||||
|
||||
hasBiasUncertaintyNanos @10 :Bool;
|
||||
biasUncertaintyNanos @11 :Float64;
|
||||
|
||||
hasDriftNanosPerSecond @12 :Bool;
|
||||
driftNanosPerSecond @13 :Float64;
|
||||
|
||||
hasDriftUncertaintyNanosPerSecond @14 :Bool;
|
||||
driftUncertaintyNanosPerSecond @15 :Float64;
|
||||
}
|
||||
|
||||
struct Measurement @0xd949bf717d77614d {
|
||||
svId @0 :Int32;
|
||||
constellation @1 :Constellation;
|
||||
|
||||
timeOffsetNanos @2 :Float64;
|
||||
state @3 :Int32;
|
||||
receivedSvTimeNanos @4 :Int64;
|
||||
receivedSvTimeUncertaintyNanos @5 :Int64;
|
||||
cn0DbHz @6 :Float64;
|
||||
pseudorangeRateMetersPerSecond @7 :Float64;
|
||||
pseudorangeRateUncertaintyMetersPerSecond @8 :Float64;
|
||||
accumulatedDeltaRangeState @9 :Int32;
|
||||
accumulatedDeltaRangeMeters @10 :Float64;
|
||||
accumulatedDeltaRangeUncertaintyMeters @11 :Float64;
|
||||
|
||||
hasCarrierFrequencyHz @12 :Bool;
|
||||
carrierFrequencyHz @13 :Float32;
|
||||
hasCarrierCycles @14 :Bool;
|
||||
carrierCycles @15 :Int64;
|
||||
hasCarrierPhase @16 :Bool;
|
||||
carrierPhase @17 :Float64;
|
||||
hasCarrierPhaseUncertainty @18 :Bool;
|
||||
carrierPhaseUncertainty @19 :Float64;
|
||||
hasSnrInDb @20 :Bool;
|
||||
snrInDb @21 :Float64;
|
||||
|
||||
multipathIndicator @22 :MultipathIndicator;
|
||||
|
||||
enum Constellation @0x9ef1f3ff0deb5ffb {
|
||||
unknown @0;
|
||||
gps @1;
|
||||
sbas @2;
|
||||
glonass @3;
|
||||
qzss @4;
|
||||
beidou @5;
|
||||
galileo @6;
|
||||
}
|
||||
|
||||
enum State @0xcbb9490adce12d72 {
|
||||
unknown @0;
|
||||
codeLock @1;
|
||||
bitSync @2;
|
||||
subframeSync @3;
|
||||
towDecoded @4;
|
||||
msecAmbiguous @5;
|
||||
symbolSync @6;
|
||||
gloStringSync @7;
|
||||
gloTodDecoded @8;
|
||||
bdsD2BitSync @9;
|
||||
bdsD2SubframeSync @10;
|
||||
galE1bcCodeLock @11;
|
||||
galE1c2ndCodeLock @12;
|
||||
galE1bPageSync @13;
|
||||
sbasSync @14;
|
||||
}
|
||||
|
||||
enum MultipathIndicator @0xc04e7b6231d4caa8 {
|
||||
unknown @0;
|
||||
detected @1;
|
||||
notDetected @2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct NavigationMessage @0xe2517b083095fd4e {
|
||||
type @0 :Int32;
|
||||
svId @1 :Int32;
|
||||
messageId @2 :Int32;
|
||||
submessageId @3 :Int32;
|
||||
data @4 :Data;
|
||||
status @5 :Status;
|
||||
|
||||
enum Status @0xec1ff7996b35366f {
|
||||
unknown @0;
|
||||
parityPassed @1;
|
||||
parityRebuilt @2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LidarPts @0xe3d6685d4e9d8f7a {
|
||||
r @0 :List(UInt16); # uint16 m*500.0
|
||||
theta @1 :List(UInt16); # uint16 deg*100.0
|
||||
reflect @2 :List(UInt8); # uint8 0-255
|
||||
|
||||
# For storing out of file.
|
||||
idx @3 :UInt64;
|
||||
|
||||
# For storing in file
|
||||
pkt @4 :Data;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,49 @@
|
|||
using Cxx = import "./include/c++.capnp";
|
||||
$Cxx.namespace("cereal");
|
||||
|
||||
@0xa086df597ef5d7a0;
|
||||
|
||||
# Geometry
|
||||
struct Point {
|
||||
x @0: Float64;
|
||||
y @1: Float64;
|
||||
z @2: Float64;
|
||||
}
|
||||
|
||||
struct PolyLine {
|
||||
points @0: List(Point);
|
||||
}
|
||||
|
||||
# Map features
|
||||
struct Lane {
|
||||
id @0 :Text;
|
||||
|
||||
leftBoundary @1 :LaneBoundary;
|
||||
rightBoundary @2 :LaneBoundary;
|
||||
|
||||
leftAdjacentId @3 :Text;
|
||||
rightAdjacentId @4 :Text;
|
||||
|
||||
inboundIds @5 :List(Text);
|
||||
outboundIds @6 :List(Text);
|
||||
|
||||
struct LaneBoundary {
|
||||
polyLine @0 :PolyLine;
|
||||
startHeading @1 :Float32; # WRT north
|
||||
}
|
||||
}
|
||||
|
||||
# Map tiles
|
||||
struct TileSummary {
|
||||
version @0 :Text;
|
||||
updatedAt @1 :UInt64; # Millis since epoch
|
||||
|
||||
level @2 :UInt8;
|
||||
x @3 :UInt16;
|
||||
y @4 :UInt16;
|
||||
}
|
||||
|
||||
struct MapTile {
|
||||
summary @0 :TileSummary;
|
||||
lanes @1 :List(Lane);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
demo
|
||||
bridge
|
||||
test_runner
|
||||
*.o
|
||||
*.os
|
||||
*.d
|
||||
*.a
|
||||
*.so
|
||||
messaging_pyx.cpp
|
||||
build/
|
|
@ -0,0 +1,252 @@
|
|||
# must be built with scons
|
||||
from msgq.ipc_pyx import Context, Poller, SubSocket, PubSocket, SocketEventHandle, toggle_fake_events, \
|
||||
set_fake_prefix, get_fake_prefix, delete_fake_prefix, wait_for_one_event
|
||||
from msgq.ipc_pyx import MultiplePublishersError, IpcError
|
||||
from msgq import fake_event_handle, pub_sock, sub_sock, drain_sock_raw, context
|
||||
|
||||
import os
|
||||
import capnp
|
||||
import time
|
||||
|
||||
from typing import Optional, List, Union, Dict, Deque
|
||||
from collections import deque
|
||||
|
||||
from cereal import log
|
||||
from cereal.services import SERVICE_LIST
|
||||
|
||||
NO_TRAVERSAL_LIMIT = 2**64-1
|
||||
|
||||
|
||||
def log_from_bytes(dat: bytes) -> capnp.lib.capnp._DynamicStructReader:
|
||||
with log.Event.from_bytes(dat, traversal_limit_in_words=NO_TRAVERSAL_LIMIT) as msg:
|
||||
return msg
|
||||
|
||||
|
||||
def new_message(service: Optional[str], size: Optional[int] = None, **kwargs) -> capnp.lib.capnp._DynamicStructBuilder:
|
||||
args = {
|
||||
'valid': False,
|
||||
'logMonoTime': int(time.monotonic() * 1e9),
|
||||
**kwargs
|
||||
}
|
||||
dat = log.Event.new_message(**args)
|
||||
if service is not None:
|
||||
if size is None:
|
||||
dat.init(service)
|
||||
else:
|
||||
dat.init(service, size)
|
||||
return dat
|
||||
|
||||
|
||||
def drain_sock(sock: SubSocket, wait_for_one: bool = False) -> List[capnp.lib.capnp._DynamicStructReader]:
|
||||
"""Receive all message currently available on the queue"""
|
||||
msgs = drain_sock_raw(sock, wait_for_one=wait_for_one)
|
||||
return [log_from_bytes(m) for m in msgs]
|
||||
|
||||
|
||||
# TODO: print when we drop packets?
|
||||
def recv_sock(sock: SubSocket, wait: bool = False) -> Optional[capnp.lib.capnp._DynamicStructReader]:
|
||||
"""Same as drain sock, but only returns latest message. Consider using conflate instead."""
|
||||
dat = None
|
||||
|
||||
while 1:
|
||||
if wait and dat is None:
|
||||
recv = sock.receive()
|
||||
else:
|
||||
recv = sock.receive(non_blocking=True)
|
||||
|
||||
if recv is None: # Timeout hit
|
||||
break
|
||||
|
||||
dat = recv
|
||||
|
||||
if dat is not None:
|
||||
dat = log_from_bytes(dat)
|
||||
|
||||
return dat
|
||||
|
||||
|
||||
def recv_one(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]:
|
||||
dat = sock.receive()
|
||||
if dat is not None:
|
||||
dat = log_from_bytes(dat)
|
||||
return dat
|
||||
|
||||
|
||||
def recv_one_or_none(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]:
|
||||
dat = sock.receive(non_blocking=True)
|
||||
if dat is not None:
|
||||
dat = log_from_bytes(dat)
|
||||
return dat
|
||||
|
||||
|
||||
def recv_one_retry(sock: SubSocket) -> capnp.lib.capnp._DynamicStructReader:
|
||||
"""Keep receiving until we get a message"""
|
||||
while True:
|
||||
dat = sock.receive()
|
||||
if dat is not None:
|
||||
return log_from_bytes(dat)
|
||||
|
||||
|
||||
class SubMaster:
|
||||
def __init__(self, services: List[str], poll: Optional[str] = None,
|
||||
ignore_alive: Optional[List[str]] = None, ignore_avg_freq: Optional[List[str]] = None,
|
||||
ignore_valid: Optional[List[str]] = None, addr: str = "127.0.0.1", frequency: Optional[float] = None):
|
||||
self.frame = -1
|
||||
self.seen = {s: False for s in services}
|
||||
self.updated = {s: False for s in services}
|
||||
self.recv_time = {s: 0. for s in services}
|
||||
self.recv_frame = {s: 0 for s in services}
|
||||
self.alive = {s: False for s in services}
|
||||
self.freq_ok = {s: False for s in services}
|
||||
self.recv_dts: Dict[str, Deque[float]] = {}
|
||||
self.sock = {}
|
||||
self.data = {}
|
||||
self.valid = {}
|
||||
self.logMonoTime = {}
|
||||
|
||||
self.max_freq = {}
|
||||
self.min_freq = {}
|
||||
|
||||
self.poller = Poller()
|
||||
polled_services = set([poll, ] if poll is not None else services)
|
||||
self.non_polled_services = set(services) - polled_services
|
||||
|
||||
self.ignore_average_freq = [] if ignore_avg_freq is None else ignore_avg_freq
|
||||
self.ignore_alive = [] if ignore_alive is None else ignore_alive
|
||||
self.ignore_valid = [] if ignore_valid is None else ignore_valid
|
||||
|
||||
self.simulation = bool(int(os.getenv("SIMULATION", "0")))
|
||||
|
||||
# if freq and poll aren't specified, assume the max to be conservative
|
||||
assert frequency is None or poll is None, "Do not specify 'frequency' - frequency of the polled service will be used."
|
||||
self.update_freq = frequency or max([SERVICE_LIST[s].frequency for s in polled_services])
|
||||
|
||||
for s in services:
|
||||
p = self.poller if s not in self.non_polled_services else None
|
||||
self.sock[s] = sub_sock(s, poller=p, addr=addr, conflate=True)
|
||||
|
||||
try:
|
||||
data = new_message(s)
|
||||
except capnp.lib.capnp.KjException:
|
||||
data = new_message(s, 0) # lists
|
||||
|
||||
self.data[s] = getattr(data.as_reader(), s)
|
||||
self.logMonoTime[s] = 0
|
||||
self.valid[s] = True # FIXME: this should default to False
|
||||
|
||||
freq = max(min([SERVICE_LIST[s].frequency, self.update_freq]), 1.)
|
||||
if s == poll:
|
||||
max_freq = freq
|
||||
min_freq = freq
|
||||
else:
|
||||
max_freq = min(freq, self.update_freq)
|
||||
if SERVICE_LIST[s].frequency >= 2*self.update_freq:
|
||||
min_freq = self.update_freq
|
||||
elif self.update_freq >= 2*SERVICE_LIST[s].frequency:
|
||||
min_freq = freq
|
||||
else:
|
||||
min_freq = min(freq, freq / 2.)
|
||||
self.max_freq[s] = max_freq*1.2
|
||||
self.min_freq[s] = min_freq*0.8
|
||||
self.recv_dts[s] = deque(maxlen=int(10*freq))
|
||||
|
||||
def __getitem__(self, s: str) -> capnp.lib.capnp._DynamicStructReader:
|
||||
return self.data[s]
|
||||
|
||||
def _check_avg_freq(self, s: str) -> bool:
|
||||
return SERVICE_LIST[s].frequency > 0.99 and (s not in self.ignore_average_freq) and (s not in self.ignore_alive)
|
||||
|
||||
def update(self, timeout: int = 100) -> None:
|
||||
msgs = []
|
||||
for sock in self.poller.poll(timeout):
|
||||
msgs.append(recv_one_or_none(sock))
|
||||
|
||||
# non-blocking receive for non-polled sockets
|
||||
for s in self.non_polled_services:
|
||||
msgs.append(recv_one_or_none(self.sock[s]))
|
||||
self.update_msgs(time.monotonic(), msgs)
|
||||
|
||||
def update_msgs(self, cur_time: float, msgs: List[capnp.lib.capnp._DynamicStructReader]) -> None:
|
||||
self.frame += 1
|
||||
self.updated = dict.fromkeys(self.updated, False)
|
||||
for msg in msgs:
|
||||
if msg is None:
|
||||
continue
|
||||
|
||||
s = msg.which()
|
||||
self.seen[s] = True
|
||||
self.updated[s] = True
|
||||
|
||||
if self.recv_time[s] > 1e-5:
|
||||
self.recv_dts[s].append(cur_time - self.recv_time[s])
|
||||
self.recv_time[s] = cur_time
|
||||
self.recv_frame[s] = self.frame
|
||||
self.data[s] = getattr(msg, s)
|
||||
self.logMonoTime[s] = msg.logMonoTime
|
||||
self.valid[s] = msg.valid
|
||||
|
||||
for s in self.data:
|
||||
if SERVICE_LIST[s].frequency > 1e-5 and not self.simulation:
|
||||
# alive if delay is within 10x the expected frequency
|
||||
self.alive[s] = (cur_time - self.recv_time[s]) < (10. / SERVICE_LIST[s].frequency)
|
||||
|
||||
# check average frequency; slow to fall, quick to recover
|
||||
dts = self.recv_dts[s]
|
||||
assert dts.maxlen is not None
|
||||
recent_dts = list(dts)[-int(dts.maxlen / 10):]
|
||||
try:
|
||||
avg_freq = 1 / (sum(dts) / len(dts))
|
||||
avg_freq_recent = 1 / (sum(recent_dts) / len(recent_dts))
|
||||
except ZeroDivisionError:
|
||||
avg_freq = 0
|
||||
avg_freq_recent = 0
|
||||
|
||||
avg_freq_ok = self.min_freq[s] <= avg_freq <= self.max_freq[s]
|
||||
recent_freq_ok = self.min_freq[s] <= avg_freq_recent <= self.max_freq[s]
|
||||
self.freq_ok[s] = avg_freq_ok or recent_freq_ok
|
||||
else:
|
||||
self.freq_ok[s] = True
|
||||
if self.simulation:
|
||||
self.alive[s] = self.seen[s] # alive is defined as seen when simulation flag set
|
||||
else:
|
||||
self.alive[s] = True
|
||||
|
||||
def all_alive(self, service_list: Optional[List[str]] = None) -> bool:
|
||||
if service_list is None:
|
||||
service_list = list(self.sock.keys())
|
||||
return all(self.alive[s] for s in service_list if s not in self.ignore_alive)
|
||||
|
||||
def all_freq_ok(self, service_list: Optional[List[str]] = None) -> bool:
|
||||
if service_list is None:
|
||||
service_list = list(self.sock.keys())
|
||||
return all(self.freq_ok[s] for s in service_list if self._check_avg_freq(s))
|
||||
|
||||
def all_valid(self, service_list: Optional[List[str]] = None) -> bool:
|
||||
if service_list is None:
|
||||
service_list = list(self.sock.keys())
|
||||
return all(self.valid[s] for s in service_list if s not in self.ignore_valid)
|
||||
|
||||
def all_checks(self, service_list: Optional[List[str]] = None) -> bool:
|
||||
return self.all_alive(service_list) and self.all_freq_ok(service_list) and self.all_valid(service_list)
|
||||
|
||||
|
||||
class PubMaster:
|
||||
def __init__(self, services: List[str]):
|
||||
self.sock = {}
|
||||
for s in services:
|
||||
self.sock[s] = pub_sock(s)
|
||||
|
||||
def send(self, s: str, dat: Union[bytes, capnp.lib.capnp._DynamicStructBuilder]) -> None:
|
||||
if not isinstance(dat, bytes):
|
||||
dat = dat.to_bytes()
|
||||
self.sock[s].send(dat)
|
||||
|
||||
def wait_for_readers_to_update(self, s: str, timeout: int, dt: float = 0.05) -> bool:
|
||||
for _ in range(int(timeout*(1./dt))):
|
||||
if self.sock[s].all_readers_updated():
|
||||
return True
|
||||
time.sleep(dt)
|
||||
return False
|
||||
|
||||
def all_readers_updated(self, s: str) -> bool:
|
||||
return self.sock[s].all_readers_updated() # type: ignore
|
|
@ -0,0 +1,92 @@
|
|||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <csignal>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
typedef void (*sighandler_t)(int sig);
|
||||
|
||||
#include "cereal/services.h"
|
||||
#include "msgq/impl_msgq.h"
|
||||
#include "msgq/impl_zmq.h"
|
||||
|
||||
std::atomic<bool> do_exit = false;
|
||||
static void set_do_exit(int sig) {
|
||||
do_exit = true;
|
||||
}
|
||||
|
||||
void sigpipe_handler(int sig) {
|
||||
assert(sig == SIGPIPE);
|
||||
std::cout << "SIGPIPE received" << std::endl;
|
||||
}
|
||||
|
||||
static std::vector<std::string> get_services(std::string whitelist_str, bool zmq_to_msgq) {
|
||||
std::vector<std::string> service_list;
|
||||
for (const auto& it : services) {
|
||||
std::string name = it.second.name;
|
||||
bool in_whitelist = whitelist_str.find(name) != std::string::npos;
|
||||
if (name == "plusFrame" || name == "uiLayoutState" || (zmq_to_msgq && !in_whitelist)) {
|
||||
continue;
|
||||
}
|
||||
service_list.push_back(name);
|
||||
}
|
||||
return service_list;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
signal(SIGPIPE, (sighandler_t)sigpipe_handler);
|
||||
signal(SIGINT, (sighandler_t)set_do_exit);
|
||||
signal(SIGTERM, (sighandler_t)set_do_exit);
|
||||
|
||||
bool zmq_to_msgq = argc > 2;
|
||||
std::string ip = zmq_to_msgq ? argv[1] : "127.0.0.1";
|
||||
std::string whitelist_str = zmq_to_msgq ? std::string(argv[2]) : "";
|
||||
|
||||
Poller *poller;
|
||||
Context *pub_context;
|
||||
Context *sub_context;
|
||||
if (zmq_to_msgq) { // republishes zmq debugging messages as msgq
|
||||
poller = new ZMQPoller();
|
||||
pub_context = new MSGQContext();
|
||||
sub_context = new ZMQContext();
|
||||
} else {
|
||||
poller = new MSGQPoller();
|
||||
pub_context = new ZMQContext();
|
||||
sub_context = new MSGQContext();
|
||||
}
|
||||
|
||||
std::map<SubSocket*, PubSocket*> sub2pub;
|
||||
for (auto endpoint : get_services(whitelist_str, zmq_to_msgq)) {
|
||||
PubSocket * pub_sock;
|
||||
SubSocket * sub_sock;
|
||||
if (zmq_to_msgq) {
|
||||
pub_sock = new MSGQPubSocket();
|
||||
sub_sock = new ZMQSubSocket();
|
||||
} else {
|
||||
pub_sock = new ZMQPubSocket();
|
||||
sub_sock = new MSGQSubSocket();
|
||||
}
|
||||
pub_sock->connect(pub_context, endpoint);
|
||||
sub_sock->connect(sub_context, endpoint, ip, false);
|
||||
|
||||
poller->registerSocket(sub_sock);
|
||||
sub2pub[sub_sock] = pub_sock;
|
||||
}
|
||||
|
||||
while (!do_exit) {
|
||||
for (auto sub_sock : poller->poll(100)) {
|
||||
Message * msg = sub_sock->receive();
|
||||
if (msg == NULL) continue;
|
||||
int ret;
|
||||
do {
|
||||
ret = sub2pub[sub_sock]->sendMessage(msg);
|
||||
} while (ret == -1 && errno == EINTR && !do_exit);
|
||||
assert(ret >= 0 || do_exit);
|
||||
delete msg;
|
||||
|
||||
if (do_exit) break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <time.h>
|
||||
|
||||
#include <capnp/serialize.h>
|
||||
|
||||
#include "cereal/gen/cpp/log.capnp.h"
|
||||
#include "msgq/ipc.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define CLOCK_BOOTTIME CLOCK_MONOTONIC
|
||||
#endif
|
||||
|
||||
#define MSG_MULTIPLE_PUBLISHERS 100
|
||||
|
||||
|
||||
class SubMaster {
|
||||
public:
|
||||
SubMaster(const std::vector<const char *> &service_list, const std::vector<const char *> &poll = {},
|
||||
const char *address = nullptr, const std::vector<const char *> &ignore_alive = {});
|
||||
void update(int timeout = 1000);
|
||||
void update_msgs(uint64_t current_time, const std::vector<std::pair<std::string, cereal::Event::Reader>> &messages);
|
||||
inline bool allAlive(const std::vector<const char *> &service_list = {}) { return all_(service_list, false, true); }
|
||||
inline bool allValid(const std::vector<const char *> &service_list = {}) { return all_(service_list, true, false); }
|
||||
inline bool allAliveAndValid(const std::vector<const char *> &service_list = {}) { return all_(service_list, true, true); }
|
||||
void drain();
|
||||
~SubMaster();
|
||||
|
||||
uint64_t frame = 0;
|
||||
bool updated(const char *name) const;
|
||||
bool alive(const char *name) const;
|
||||
bool valid(const char *name) const;
|
||||
uint64_t rcv_frame(const char *name) const;
|
||||
uint64_t rcv_time(const char *name) const;
|
||||
cereal::Event::Reader &operator[](const char *name) const;
|
||||
|
||||
private:
|
||||
bool all_(const std::vector<const char *> &service_list, bool valid, bool alive);
|
||||
Poller *poller_ = nullptr;
|
||||
struct SubMessage;
|
||||
std::map<SubSocket *, SubMessage *> messages_;
|
||||
std::map<std::string, SubMessage *> services_;
|
||||
};
|
||||
|
||||
class MessageBuilder : public capnp::MallocMessageBuilder {
|
||||
public:
|
||||
MessageBuilder() = default;
|
||||
|
||||
cereal::Event::Builder initEvent(bool valid = true) {
|
||||
cereal::Event::Builder event = initRoot<cereal::Event>();
|
||||
struct timespec t;
|
||||
clock_gettime(CLOCK_BOOTTIME, &t);
|
||||
uint64_t current_time = t.tv_sec * 1000000000ULL + t.tv_nsec;
|
||||
event.setLogMonoTime(current_time);
|
||||
event.setValid(valid);
|
||||
return event;
|
||||
}
|
||||
|
||||
kj::ArrayPtr<capnp::byte> toBytes() {
|
||||
heapArray_ = capnp::messageToFlatArray(*this);
|
||||
return heapArray_.asBytes();
|
||||
}
|
||||
|
||||
size_t getSerializedSize() {
|
||||
return capnp::computeSerializedSizeInWords(*this) * sizeof(capnp::word);
|
||||
}
|
||||
|
||||
int serializeToBuffer(unsigned char *buffer, size_t buffer_size) {
|
||||
size_t serialized_size = getSerializedSize();
|
||||
if (serialized_size > buffer_size) { return -1; }
|
||||
kj::ArrayOutputStream out(kj::ArrayPtr<capnp::byte>(buffer, buffer_size));
|
||||
capnp::writeMessage(out, *this);
|
||||
return serialized_size;
|
||||
}
|
||||
|
||||
private:
|
||||
kj::Array<capnp::word> heapArray_;
|
||||
};
|
||||
|
||||
class PubMaster {
|
||||
public:
|
||||
PubMaster(const std::vector<const char *> &service_list);
|
||||
inline int send(const char *name, capnp::byte *data, size_t size) { return sockets_.at(name)->send((char *)data, size); }
|
||||
int send(const char *name, MessageBuilder &msg);
|
||||
~PubMaster();
|
||||
|
||||
private:
|
||||
std::map<std::string, PubSocket *> sockets_;
|
||||
};
|
||||
|
||||
class AlignedBuffer {
|
||||
public:
|
||||
kj::ArrayPtr<const capnp::word> align(const char *data, const size_t size) {
|
||||
words_size = size / sizeof(capnp::word) + 1;
|
||||
if (aligned_buf.size() < words_size) {
|
||||
aligned_buf = kj::heapArray<capnp::word>(words_size < 512 ? 512 : words_size);
|
||||
}
|
||||
memcpy(aligned_buf.begin(), data, size);
|
||||
return aligned_buf.slice(0, words_size);
|
||||
}
|
||||
inline kj::ArrayPtr<const capnp::word> align(Message *m) {
|
||||
return align(m->getData(), m->getSize());
|
||||
}
|
||||
private:
|
||||
kj::Array<capnp::word> aligned_buf;
|
||||
size_t words_size;
|
||||
};
|
|
@ -0,0 +1,211 @@
|
|||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
|
||||
#include "cereal/services.h"
|
||||
#include "cereal/messaging/messaging.h"
|
||||
|
||||
|
||||
const bool SIMULATION = (getenv("SIMULATION") != nullptr) && (std::string(getenv("SIMULATION")) == "1");
|
||||
|
||||
static inline uint64_t nanos_since_boot() {
|
||||
struct timespec t;
|
||||
clock_gettime(CLOCK_BOOTTIME, &t);
|
||||
return t.tv_sec * 1000000000ULL + t.tv_nsec;
|
||||
}
|
||||
|
||||
static inline bool inList(const std::vector<const char *> &list, const char *value) {
|
||||
for (auto &v : list) {
|
||||
if (strcmp(value, v) == 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class MessageContext {
|
||||
public:
|
||||
MessageContext() : ctx_(nullptr) {}
|
||||
~MessageContext() { delete ctx_; }
|
||||
inline Context *context() {
|
||||
std::call_once(init_flag, [=]() { ctx_ = Context::create(); });
|
||||
return ctx_;
|
||||
}
|
||||
private:
|
||||
Context *ctx_;
|
||||
std::once_flag init_flag;
|
||||
};
|
||||
|
||||
MessageContext message_context;
|
||||
|
||||
struct SubMaster::SubMessage {
|
||||
std::string name;
|
||||
SubSocket *socket = nullptr;
|
||||
int freq = 0;
|
||||
bool updated = false, alive = false, valid = true, ignore_alive;
|
||||
uint64_t rcv_time = 0, rcv_frame = 0;
|
||||
void *allocated_msg_reader = nullptr;
|
||||
bool is_polled = false;
|
||||
capnp::FlatArrayMessageReader *msg_reader = nullptr;
|
||||
AlignedBuffer aligned_buf;
|
||||
cereal::Event::Reader event;
|
||||
};
|
||||
|
||||
SubMaster::SubMaster(const std::vector<const char *> &service_list, const std::vector<const char *> &poll,
|
||||
const char *address, const std::vector<const char *> &ignore_alive) {
|
||||
poller_ = Poller::create();
|
||||
for (auto name : service_list) {
|
||||
assert(services.count(std::string(name)) > 0);
|
||||
|
||||
service serv = services.at(std::string(name));
|
||||
SubSocket *socket = SubSocket::create(message_context.context(), name, address ? address : "127.0.0.1", true);
|
||||
assert(socket != 0);
|
||||
bool is_polled = inList(poll, name) || poll.empty();
|
||||
if (is_polled) poller_->registerSocket(socket);
|
||||
SubMessage *m = new SubMessage{
|
||||
.name = name,
|
||||
.socket = socket,
|
||||
.freq = serv.frequency,
|
||||
.ignore_alive = inList(ignore_alive, name),
|
||||
.allocated_msg_reader = malloc(sizeof(capnp::FlatArrayMessageReader)),
|
||||
.is_polled = is_polled};
|
||||
m->msg_reader = new (m->allocated_msg_reader) capnp::FlatArrayMessageReader({});
|
||||
messages_[socket] = m;
|
||||
services_[name] = m;
|
||||
}
|
||||
}
|
||||
|
||||
void SubMaster::update(int timeout) {
|
||||
for (auto &kv : messages_) kv.second->updated = false;
|
||||
|
||||
auto sockets = poller_->poll(timeout);
|
||||
|
||||
// add non-polled sockets for non-blocking receive
|
||||
for (auto &kv : messages_) {
|
||||
SubMessage *m = kv.second;
|
||||
SubSocket *s = kv.first;
|
||||
if (!m->is_polled) sockets.push_back(s);
|
||||
}
|
||||
|
||||
uint64_t current_time = nanos_since_boot();
|
||||
|
||||
std::vector<std::pair<std::string, cereal::Event::Reader>> messages;
|
||||
|
||||
for (auto s : sockets) {
|
||||
Message *msg = s->receive(true);
|
||||
if (msg == nullptr) continue;
|
||||
|
||||
SubMessage *m = messages_.at(s);
|
||||
|
||||
m->msg_reader->~FlatArrayMessageReader();
|
||||
capnp::ReaderOptions options;
|
||||
options.traversalLimitInWords = kj::maxValue; // Don't limit
|
||||
m->msg_reader = new (m->allocated_msg_reader) capnp::FlatArrayMessageReader(m->aligned_buf.align(msg), options);
|
||||
delete msg;
|
||||
messages.push_back({m->name, m->msg_reader->getRoot<cereal::Event>()});
|
||||
}
|
||||
|
||||
update_msgs(current_time, messages);
|
||||
}
|
||||
|
||||
void SubMaster::update_msgs(uint64_t current_time, const std::vector<std::pair<std::string, cereal::Event::Reader>> &messages){
|
||||
if (++frame == UINT64_MAX) frame = 1;
|
||||
|
||||
for (auto &kv : messages) {
|
||||
auto m_find = services_.find(kv.first);
|
||||
if (m_find == services_.end()){
|
||||
continue;
|
||||
}
|
||||
SubMessage *m = m_find->second;
|
||||
m->event = kv.second;
|
||||
m->updated = true;
|
||||
m->rcv_time = current_time;
|
||||
m->rcv_frame = frame;
|
||||
m->valid = m->event.getValid();
|
||||
if (SIMULATION) m->alive = true;
|
||||
}
|
||||
|
||||
if (!SIMULATION) {
|
||||
for (auto &kv : messages_) {
|
||||
SubMessage *m = kv.second;
|
||||
m->alive = (m->freq <= (1e-5) || ((current_time - m->rcv_time) * (1e-9)) < (10.0 / m->freq));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SubMaster::all_(const std::vector<const char *> &service_list, bool valid, bool alive) {
|
||||
int found = 0;
|
||||
for (auto &kv : messages_) {
|
||||
SubMessage *m = kv.second;
|
||||
if (service_list.size() == 0 || inList(service_list, m->name.c_str())) {
|
||||
found += (!valid || m->valid) && (!alive || (m->alive || m->ignore_alive));
|
||||
}
|
||||
}
|
||||
return service_list.size() == 0 ? found == messages_.size() : found == service_list.size();
|
||||
}
|
||||
|
||||
void SubMaster::drain() {
|
||||
while (true) {
|
||||
auto polls = poller_->poll(0);
|
||||
if (polls.size() == 0)
|
||||
break;
|
||||
|
||||
for (auto sock : polls) {
|
||||
Message *msg = sock->receive(true);
|
||||
delete msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SubMaster::updated(const char *name) const {
|
||||
return services_.at(name)->updated;
|
||||
}
|
||||
|
||||
bool SubMaster::alive(const char *name) const {
|
||||
return services_.at(name)->alive;
|
||||
}
|
||||
|
||||
bool SubMaster::valid(const char *name) const {
|
||||
return services_.at(name)->valid;
|
||||
}
|
||||
|
||||
uint64_t SubMaster::rcv_frame(const char *name) const {
|
||||
return services_.at(name)->rcv_frame;
|
||||
}
|
||||
|
||||
uint64_t SubMaster::rcv_time(const char *name) const {
|
||||
return services_.at(name)->rcv_time;
|
||||
}
|
||||
|
||||
cereal::Event::Reader &SubMaster::operator[](const char *name) const {
|
||||
return services_.at(name)->event;
|
||||
}
|
||||
|
||||
SubMaster::~SubMaster() {
|
||||
delete poller_;
|
||||
for (auto &kv : messages_) {
|
||||
SubMessage *m = kv.second;
|
||||
m->msg_reader->~FlatArrayMessageReader();
|
||||
free(m->allocated_msg_reader);
|
||||
delete m->socket;
|
||||
delete m;
|
||||
}
|
||||
}
|
||||
|
||||
PubMaster::PubMaster(const std::vector<const char *> &service_list) {
|
||||
for (auto name : service_list) {
|
||||
assert(services.count(name) > 0);
|
||||
PubSocket *socket = PubSocket::create(message_context.context(), name);
|
||||
assert(socket);
|
||||
sockets_[name] = socket;
|
||||
}
|
||||
}
|
||||
|
||||
int PubMaster::send(const char *name, MessageBuilder &msg) {
|
||||
auto bytes = msg.toBytes();
|
||||
return send(name, bytes.begin(), bytes.size());
|
||||
}
|
||||
|
||||
PubMaster::~PubMaster() {
|
||||
for (auto s : sockets_) delete s.second;
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import capnp
|
||||
import multiprocessing
|
||||
import numbers
|
||||
import random
|
||||
import threading
|
||||
import time
|
||||
import unittest
|
||||
from parameterized import parameterized
|
||||
|
||||
from cereal import log, car
|
||||
import cereal.messaging as messaging
|
||||
from cereal.services import SERVICE_LIST
|
||||
|
||||
events = [evt for evt in log.Event.schema.union_fields if evt in SERVICE_LIST.keys()]
|
||||
|
||||
def random_sock():
|
||||
return random.choice(events)
|
||||
|
||||
def random_socks(num_socks=10):
|
||||
return list({random_sock() for _ in range(num_socks)})
|
||||
|
||||
def random_bytes(length=1000):
|
||||
return bytes([random.randrange(0xFF) for _ in range(length)])
|
||||
|
||||
def zmq_sleep(t=1):
|
||||
if "ZMQ" in os.environ:
|
||||
time.sleep(t)
|
||||
|
||||
def zmq_expected_failure(func):
|
||||
if "ZMQ" in os.environ:
|
||||
return unittest.expectedFailure(func)
|
||||
else:
|
||||
return func
|
||||
|
||||
|
||||
# TODO: this should take any capnp struct and returrn a msg with random populated data
|
||||
def random_carstate():
|
||||
fields = ["vEgo", "aEgo", "gas", "steeringAngleDeg"]
|
||||
msg = messaging.new_message("carState")
|
||||
cs = msg.carState
|
||||
for f in fields:
|
||||
setattr(cs, f, random.random() * 10)
|
||||
return msg
|
||||
|
||||
# TODO: this should compare any capnp structs
|
||||
def assert_carstate(cs1, cs2):
|
||||
for f in car.CarState.schema.non_union_fields:
|
||||
# TODO: check all types
|
||||
val1, val2 = getattr(cs1, f), getattr(cs2, f)
|
||||
if isinstance(val1, numbers.Number):
|
||||
assert val1 == val2, f"{f}: sent '{val1}' vs recvd '{val2}'"
|
||||
|
||||
def delayed_send(delay, sock, dat):
|
||||
def send_func():
|
||||
sock.send(dat)
|
||||
threading.Timer(delay, send_func).start()
|
||||
|
||||
|
||||
class TestMessaging(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# TODO: ZMQ tests are too slow; all sleeps will need to be
|
||||
# replaced with logic to block on the necessary condition
|
||||
if "ZMQ" in os.environ:
|
||||
raise unittest.SkipTest
|
||||
|
||||
# ZMQ pub socket takes too long to die
|
||||
# sleep to prevent multiple publishers error between tests
|
||||
zmq_sleep()
|
||||
|
||||
@parameterized.expand(events)
|
||||
def test_new_message(self, evt):
|
||||
try:
|
||||
msg = messaging.new_message(evt)
|
||||
except capnp.lib.capnp.KjException:
|
||||
msg = messaging.new_message(evt, random.randrange(200))
|
||||
self.assertLess(time.monotonic() - msg.logMonoTime, 0.1)
|
||||
self.assertFalse(msg.valid)
|
||||
self.assertEqual(evt, msg.which())
|
||||
|
||||
@parameterized.expand(events)
|
||||
def test_pub_sock(self, evt):
|
||||
messaging.pub_sock(evt)
|
||||
|
||||
@parameterized.expand(events)
|
||||
def test_sub_sock(self, evt):
|
||||
messaging.sub_sock(evt)
|
||||
|
||||
@parameterized.expand([
|
||||
(messaging.drain_sock, capnp._DynamicStructReader),
|
||||
(messaging.drain_sock_raw, bytes),
|
||||
])
|
||||
def test_drain_sock(self, func, expected_type):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sub_sock = messaging.sub_sock(sock, timeout=1000)
|
||||
zmq_sleep()
|
||||
|
||||
# no wait and no msgs in queue
|
||||
msgs = func(sub_sock)
|
||||
self.assertIsInstance(msgs, list)
|
||||
self.assertEqual(len(msgs), 0)
|
||||
|
||||
# no wait but msgs are queued up
|
||||
num_msgs = random.randrange(3, 10)
|
||||
for _ in range(num_msgs):
|
||||
pub_sock.send(messaging.new_message(sock).to_bytes())
|
||||
time.sleep(0.1)
|
||||
msgs = func(sub_sock)
|
||||
self.assertIsInstance(msgs, list)
|
||||
self.assertTrue(all(isinstance(msg, expected_type) for msg in msgs))
|
||||
self.assertEqual(len(msgs), num_msgs)
|
||||
|
||||
def test_recv_sock(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sub_sock = messaging.sub_sock(sock, timeout=100)
|
||||
zmq_sleep()
|
||||
|
||||
# no wait and no msg in queue, socket should timeout
|
||||
recvd = messaging.recv_sock(sub_sock)
|
||||
self.assertTrue(recvd is None)
|
||||
|
||||
# no wait and one msg in queue
|
||||
msg = random_carstate()
|
||||
pub_sock.send(msg.to_bytes())
|
||||
time.sleep(0.01)
|
||||
recvd = messaging.recv_sock(sub_sock)
|
||||
self.assertIsInstance(recvd, capnp._DynamicStructReader)
|
||||
# https://github.com/python/mypy/issues/13038
|
||||
assert_carstate(msg.carState, recvd.carState)
|
||||
|
||||
def test_recv_one(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sub_sock = messaging.sub_sock(sock, timeout=1000)
|
||||
zmq_sleep()
|
||||
|
||||
# no msg in queue, socket should timeout
|
||||
recvd = messaging.recv_one(sub_sock)
|
||||
self.assertTrue(recvd is None)
|
||||
|
||||
# one msg in queue
|
||||
msg = random_carstate()
|
||||
pub_sock.send(msg.to_bytes())
|
||||
recvd = messaging.recv_one(sub_sock)
|
||||
self.assertIsInstance(recvd, capnp._DynamicStructReader)
|
||||
assert_carstate(msg.carState, recvd.carState)
|
||||
|
||||
@zmq_expected_failure
|
||||
def test_recv_one_or_none(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sub_sock = messaging.sub_sock(sock)
|
||||
zmq_sleep()
|
||||
|
||||
# no msg in queue, socket shouldn't block
|
||||
recvd = messaging.recv_one_or_none(sub_sock)
|
||||
self.assertTrue(recvd is None)
|
||||
|
||||
# one msg in queue
|
||||
msg = random_carstate()
|
||||
pub_sock.send(msg.to_bytes())
|
||||
recvd = messaging.recv_one_or_none(sub_sock)
|
||||
self.assertIsInstance(recvd, capnp._DynamicStructReader)
|
||||
assert_carstate(msg.carState, recvd.carState)
|
||||
|
||||
def test_recv_one_retry(self):
|
||||
sock = "carState"
|
||||
sock_timeout = 0.1
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sub_sock = messaging.sub_sock(sock, timeout=round(sock_timeout*1000))
|
||||
zmq_sleep()
|
||||
|
||||
# this test doesn't work with ZMQ since multiprocessing interrupts it
|
||||
if "ZMQ" not in os.environ:
|
||||
# wait 15 socket timeouts and make sure it's still retrying
|
||||
p = multiprocessing.Process(target=messaging.recv_one_retry, args=(sub_sock,))
|
||||
p.start()
|
||||
time.sleep(sock_timeout*15)
|
||||
self.assertTrue(p.is_alive())
|
||||
p.terminate()
|
||||
|
||||
# wait 15 socket timeouts before sending
|
||||
msg = random_carstate()
|
||||
delayed_send(sock_timeout*15, pub_sock, msg.to_bytes())
|
||||
start_time = time.monotonic()
|
||||
recvd = messaging.recv_one_retry(sub_sock)
|
||||
self.assertGreaterEqual(time.monotonic() - start_time, sock_timeout*15)
|
||||
self.assertIsInstance(recvd, capnp._DynamicStructReader)
|
||||
assert_carstate(msg.carState, recvd.carState)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -0,0 +1,163 @@
|
|||
#!/usr/bin/env python3
|
||||
import random
|
||||
import time
|
||||
from typing import Sized, cast
|
||||
import unittest
|
||||
|
||||
import cereal.messaging as messaging
|
||||
from cereal.messaging.tests.test_messaging import events, random_sock, random_socks, \
|
||||
random_bytes, random_carstate, assert_carstate, \
|
||||
zmq_sleep
|
||||
|
||||
|
||||
class TestSubMaster(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
# ZMQ pub socket takes too long to die
|
||||
# sleep to prevent multiple publishers error between tests
|
||||
zmq_sleep(3)
|
||||
|
||||
def test_init(self):
|
||||
sm = messaging.SubMaster(events)
|
||||
for p in [sm.updated, sm.recv_time, sm.recv_frame, sm.alive,
|
||||
sm.sock, sm.data, sm.logMonoTime, sm.valid]:
|
||||
self.assertEqual(len(cast(Sized, p)), len(events))
|
||||
|
||||
def test_init_state(self):
|
||||
socks = random_socks()
|
||||
sm = messaging.SubMaster(socks)
|
||||
self.assertEqual(sm.frame, -1)
|
||||
self.assertFalse(any(sm.updated.values()))
|
||||
self.assertFalse(any(sm.alive.values()))
|
||||
self.assertTrue(all(t == 0. for t in sm.recv_time.values()))
|
||||
self.assertTrue(all(f == 0 for f in sm.recv_frame.values()))
|
||||
self.assertTrue(all(t == 0 for t in sm.logMonoTime.values()))
|
||||
|
||||
for p in [sm.updated, sm.recv_time, sm.recv_frame, sm.alive,
|
||||
sm.sock, sm.data, sm.logMonoTime, sm.valid]:
|
||||
self.assertEqual(len(cast(Sized, p)), len(socks))
|
||||
|
||||
def test_getitem(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sm = messaging.SubMaster([sock,])
|
||||
zmq_sleep()
|
||||
|
||||
msg = random_carstate()
|
||||
pub_sock.send(msg.to_bytes())
|
||||
sm.update(1000)
|
||||
assert_carstate(msg.carState, sm[sock])
|
||||
|
||||
# TODO: break this test up to individually test SubMaster.update and SubMaster.update_msgs
|
||||
def test_update(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sm = messaging.SubMaster([sock,])
|
||||
zmq_sleep()
|
||||
|
||||
for i in range(10):
|
||||
msg = messaging.new_message(sock)
|
||||
pub_sock.send(msg.to_bytes())
|
||||
sm.update(1000)
|
||||
self.assertEqual(sm.frame, i)
|
||||
self.assertTrue(all(sm.updated.values()))
|
||||
|
||||
def test_update_timeout(self):
|
||||
sock = random_sock()
|
||||
sm = messaging.SubMaster([sock,])
|
||||
for _ in range(5):
|
||||
timeout = random.randrange(1000, 5000)
|
||||
start_time = time.monotonic()
|
||||
sm.update(timeout)
|
||||
t = time.monotonic() - start_time
|
||||
self.assertGreaterEqual(t, timeout/1000.)
|
||||
self.assertLess(t, 5)
|
||||
self.assertFalse(any(sm.updated.values()))
|
||||
|
||||
def test_avg_frequency_checks(self):
|
||||
for poll in (True, False):
|
||||
sm = messaging.SubMaster(["modelV2", "carParams", "carState", "cameraOdometry", "liveCalibration"],
|
||||
poll=("modelV2" if poll else None),
|
||||
frequency=(20. if not poll else None))
|
||||
|
||||
checks = {
|
||||
"carState": (20, 20),
|
||||
"modelV2": (20, 20 if poll else 10),
|
||||
"cameraOdometry": (20, 10),
|
||||
"liveCalibration": (4, 4),
|
||||
"carParams": (None, None),
|
||||
}
|
||||
|
||||
for service, (max_freq, min_freq) in checks.items():
|
||||
if max_freq is not None:
|
||||
assert sm._check_avg_freq(service)
|
||||
assert sm.max_freq[service] == max_freq*1.2
|
||||
assert sm.min_freq[service] == min_freq*0.8
|
||||
else:
|
||||
assert not sm._check_avg_freq(service)
|
||||
|
||||
def test_alive(self):
|
||||
pass
|
||||
|
||||
def test_ignore_alive(self):
|
||||
pass
|
||||
|
||||
def test_valid(self):
|
||||
pass
|
||||
|
||||
# SubMaster should always conflate
|
||||
def test_conflate(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sm = messaging.SubMaster([sock,])
|
||||
|
||||
n = 10
|
||||
for i in range(n+1):
|
||||
msg = messaging.new_message(sock)
|
||||
msg.carState.vEgo = i
|
||||
pub_sock.send(msg.to_bytes())
|
||||
time.sleep(0.01)
|
||||
sm.update(1000)
|
||||
self.assertEqual(sm[sock].vEgo, n)
|
||||
|
||||
|
||||
class TestPubMaster(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
# ZMQ pub socket takes too long to die
|
||||
# sleep to prevent multiple publishers error between tests
|
||||
zmq_sleep(3)
|
||||
|
||||
def test_init(self):
|
||||
messaging.PubMaster(events)
|
||||
|
||||
def test_send(self):
|
||||
socks = random_socks()
|
||||
pm = messaging.PubMaster(socks)
|
||||
sub_socks = {s: messaging.sub_sock(s, conflate=True, timeout=1000) for s in socks}
|
||||
zmq_sleep()
|
||||
|
||||
# PubMaster accepts either a capnp msg builder or bytes
|
||||
for capnp in [True, False]:
|
||||
for i in range(100):
|
||||
sock = socks[i % len(socks)]
|
||||
|
||||
if capnp:
|
||||
try:
|
||||
msg = messaging.new_message(sock)
|
||||
except Exception:
|
||||
msg = messaging.new_message(sock, random.randrange(50))
|
||||
else:
|
||||
msg = random_bytes()
|
||||
|
||||
pm.send(sock, msg)
|
||||
recvd = sub_socks[sock].receive()
|
||||
|
||||
if capnp:
|
||||
msg.clear_write_flag()
|
||||
msg = msg.to_bytes()
|
||||
self.assertEqual(msg, recvd, i)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import tempfile
|
||||
from typing import Dict
|
||||
import unittest
|
||||
from parameterized import parameterized
|
||||
|
||||
import cereal.services as services
|
||||
from cereal.services import SERVICE_LIST
|
||||
|
||||
|
||||
class TestServices(unittest.TestCase):
|
||||
|
||||
@parameterized.expand(SERVICE_LIST.keys())
|
||||
def test_services(self, s):
|
||||
service = SERVICE_LIST[s]
|
||||
self.assertTrue(service.frequency <= 104)
|
||||
|
||||
def test_generated_header(self):
|
||||
with tempfile.NamedTemporaryFile(suffix=".h") as f:
|
||||
ret = os.system(f"python3 {services.__file__} > {f.name} && clang++ {f.name}")
|
||||
self.assertEqual(ret, 0, "generated services header is not valid C")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -0,0 +1,129 @@
|
|||
#!/usr/bin/env python3
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class Service:
|
||||
def __init__(self, should_log: bool, frequency: float, decimation: Optional[int] = None):
|
||||
self.should_log = should_log
|
||||
self.frequency = frequency
|
||||
self.decimation = decimation
|
||||
|
||||
|
||||
_services: dict[str, tuple] = {
|
||||
# service: (should_log, frequency, qlog decimation (optional))
|
||||
# note: the "EncodeIdx" packets will still be in the log
|
||||
"gyroscope": (True, 104., 104),
|
||||
"gyroscope2": (True, 100., 100),
|
||||
"accelerometer": (True, 104., 104),
|
||||
"accelerometer2": (True, 100., 100),
|
||||
"magnetometer": (True, 25., 25),
|
||||
"lightSensor": (True, 100., 100),
|
||||
"temperatureSensor": (True, 2., 200),
|
||||
"temperatureSensor2": (True, 2., 200),
|
||||
"gpsNMEA": (True, 9.),
|
||||
"deviceState": (True, 2., 1),
|
||||
"can": (True, 100., 1223), # decimation gives ~5 msgs in a full segment
|
||||
"controlsState": (True, 100., 10),
|
||||
"pandaStates": (True, 10., 1),
|
||||
"peripheralState": (True, 2., 1),
|
||||
"radarState": (True, 20., 5),
|
||||
"roadEncodeIdx": (False, 20., 1),
|
||||
"liveTracks": (True, 20.),
|
||||
"sendcan": (True, 100., 139),
|
||||
"logMessage": (True, 0.),
|
||||
"errorLogMessage": (True, 0., 1),
|
||||
"liveCalibration": (True, 4., 4),
|
||||
"liveTorqueParameters": (True, 4., 1),
|
||||
"androidLog": (True, 0.),
|
||||
"carState": (True, 100., 10),
|
||||
"carControl": (True, 100., 10),
|
||||
"carOutput": (True, 100., 10),
|
||||
"longitudinalPlan": (True, 20., 5),
|
||||
"procLog": (True, 0.5, 15),
|
||||
"gpsLocationExternal": (True, 10., 10),
|
||||
"gpsLocation": (True, 1., 1),
|
||||
"ubloxGnss": (True, 10.),
|
||||
"qcomGnss": (True, 2.),
|
||||
"gnssMeasurements": (True, 10., 10),
|
||||
"clocks": (True, 0.1, 1),
|
||||
"ubloxRaw": (True, 20.),
|
||||
"liveLocationKalman": (True, 20., 5),
|
||||
"liveParameters": (True, 20., 5),
|
||||
"cameraOdometry": (True, 20., 5),
|
||||
"lateralPlanDEPRECATED": (True, 20., 5),
|
||||
"thumbnail": (True, 0.2, 1),
|
||||
"onroadEvents": (True, 1., 1),
|
||||
"carParams": (True, 0.02, 1),
|
||||
"roadCameraState": (True, 20., 20),
|
||||
"driverCameraState": (True, 20., 20),
|
||||
"driverEncodeIdx": (False, 20., 1),
|
||||
"driverStateV2": (True, 20., 10),
|
||||
"driverMonitoringState": (True, 20., 10),
|
||||
"wideRoadEncodeIdx": (False, 20., 1),
|
||||
"wideRoadCameraState": (True, 20., 20),
|
||||
"modelV2": (True, 20., 40),
|
||||
"managerState": (True, 2., 1),
|
||||
"uploaderState": (True, 0., 1),
|
||||
"navInstruction": (True, 1., 10),
|
||||
"navRoute": (True, 0.),
|
||||
"navThumbnail": (True, 0.),
|
||||
"navModelDEPRECATED": (True, 2., 4.),
|
||||
"mapRenderState": (True, 2., 1.),
|
||||
"uiPlan": (True, 20., 40.),
|
||||
"qRoadEncodeIdx": (False, 20.),
|
||||
"userFlag": (True, 0., 1),
|
||||
"microphone": (True, 10., 10),
|
||||
|
||||
"controlsStateSP": (True, 100., 10),
|
||||
"longitudinalPlanSP": (True, 20., 5),
|
||||
"lateralPlanSPDEPRECATED": (True, 20., 5),
|
||||
"driverMonitoringStateSP": (True, 20., 10),
|
||||
"liveMapDataSP": (True, 0.),
|
||||
"e2eLongStateSP": (True, 0.),
|
||||
"modelV2SP": (True, 20., 40),
|
||||
|
||||
# debug
|
||||
"uiDebug": (True, 0., 1),
|
||||
"testJoystick": (True, 0.),
|
||||
"roadEncodeData": (False, 20.),
|
||||
"driverEncodeData": (False, 20.),
|
||||
"wideRoadEncodeData": (False, 20.),
|
||||
"qRoadEncodeData": (False, 20.),
|
||||
"livestreamWideRoadEncodeIdx": (False, 20.),
|
||||
"livestreamRoadEncodeIdx": (False, 20.),
|
||||
"livestreamDriverEncodeIdx": (False, 20.),
|
||||
"livestreamWideRoadEncodeData": (False, 20.),
|
||||
"livestreamRoadEncodeData": (False, 20.),
|
||||
"livestreamDriverEncodeData": (False, 20.),
|
||||
"customReservedRawData0": (True, 0.),
|
||||
"customReservedRawData1": (True, 0.),
|
||||
"customReservedRawData2": (True, 0.),
|
||||
}
|
||||
SERVICE_LIST = {name: Service(*vals) for
|
||||
idx, (name, vals) in enumerate(_services.items())}
|
||||
|
||||
|
||||
def build_header():
|
||||
h = ""
|
||||
h += "/* THIS IS AN AUTOGENERATED FILE, PLEASE EDIT services.py */\n"
|
||||
h += "#ifndef __SERVICES_H\n"
|
||||
h += "#define __SERVICES_H\n"
|
||||
|
||||
h += "#include <map>\n"
|
||||
h += "#include <string>\n"
|
||||
|
||||
h += "struct service { std::string name; bool should_log; int frequency; int decimation; };\n"
|
||||
h += "static std::map<std::string, service> services = {\n"
|
||||
for k, v in SERVICE_LIST.items():
|
||||
should_log = "true" if v.should_log else "false"
|
||||
decimation = -1 if v.decimation is None else v.decimation
|
||||
h += ' { "%s", {"%s", %s, %d, %d}},\n' % \
|
||||
(k, k, should_log, v.frequency, decimation)
|
||||
h += "};\n"
|
||||
|
||||
h += "#endif\n"
|
||||
return h
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(build_header())
|
|
@ -1,5 +1,5 @@
|
|||
from functools import cache
|
||||
import subprocess
|
||||
from openpilot.common.utils import cache
|
||||
from openpilot.common.run import run_cmd, run_cmd_default
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
HTML_REPLACEMENTS = [
|
||||
(r'&', r'&'),
|
||||
(r'"', r'"'),
|
||||
]
|
||||
|
||||
def parse_markdown(text: str, tab_length: int = 2) -> str:
|
||||
lines = text.split("\n")
|
||||
output: list[str] = []
|
||||
list_level = 0
|
||||
|
||||
def end_outstanding_lists(level: int, end_level: int) -> int:
|
||||
while level > end_level:
|
||||
level -= 1
|
||||
output.append("</ul>")
|
||||
if level > 0:
|
||||
output.append("</li>")
|
||||
return end_level
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
if i + 1 < len(lines) and lines[i + 1].startswith("==="): # heading
|
||||
output.append(f"<h1>{line}</h1>")
|
||||
elif line.startswith("==="):
|
||||
pass
|
||||
elif line.lstrip().startswith("* "): # list
|
||||
line_level = 1 + line.count(" " * tab_length, 0, line.index("*"))
|
||||
if list_level >= line_level:
|
||||
list_level = end_outstanding_lists(list_level, line_level)
|
||||
else:
|
||||
list_level += 1
|
||||
if list_level > 1:
|
||||
output[-1] = output[-1].replace("</li>", "")
|
||||
output.append("<ul>")
|
||||
output.append(f"<li>{line.replace('*', '', 1).lstrip()}</li>")
|
||||
else:
|
||||
list_level = end_outstanding_lists(list_level, 0)
|
||||
if len(line) > 0:
|
||||
output.append(line)
|
||||
|
||||
end_outstanding_lists(list_level, 0)
|
||||
output_str = "\n".join(output) + "\n"
|
||||
|
||||
for (fr, to) in HTML_REPLACEMENTS:
|
||||
output_str = output_str.replace(fr, to)
|
||||
|
||||
return output_str
|
|
@ -9,7 +9,7 @@ public:
|
|||
~RateKeeper() {}
|
||||
bool keepTime();
|
||||
bool monitorTime();
|
||||
inline double frame() const { return frame_; }
|
||||
inline uint64_t frame() const { return frame_; }
|
||||
inline double remaining() const { return remaining_; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -14,7 +14,7 @@ from openpilot.system.hardware import PC
|
|||
# time step for each process
|
||||
DT_CTRL = 0.01 # controlsd
|
||||
DT_MDL = 0.05 # model
|
||||
DT_TRML = 0.5 # thermald and manager
|
||||
DT_HW = 0.5 # hardwared and manager
|
||||
DT_DMON = 0.05 # driver monitoring
|
||||
|
||||
|
||||
|
@ -25,7 +25,7 @@ class Priority:
|
|||
CTRL_LOW = 51 # plannerd & radard
|
||||
|
||||
# CORE 3
|
||||
# - boardd = 55
|
||||
# - pandad = 55
|
||||
CTRL_HIGH = 53
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import os
|
||||
|
||||
from openpilot.common.basedir import BASEDIR
|
||||
from openpilot.common.markdown import parse_markdown
|
||||
|
||||
|
||||
class TestMarkdown:
|
||||
def test_all_release_notes(self):
|
||||
with open(os.path.join(BASEDIR, "RELEASES.md")) as f:
|
||||
release_notes = f.read().split("\n\n")
|
||||
assert len(release_notes) > 10
|
||||
|
||||
for rn in release_notes:
|
||||
md = parse_markdown(rn)
|
||||
assert len(md) > 0
|
|
@ -1,5 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openpilot.common.transformations.coordinates as coord
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import numpy as np
|
||||
|
||||
from openpilot.common.transformations.orientation import euler2quat, quat2euler, euler2rot, rot2euler, \
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
from collections.abc import Callable
|
||||
from functools import lru_cache
|
||||
from typing import TypeVar
|
||||
|
||||
|
||||
_RT = TypeVar("_RT")
|
||||
|
||||
|
||||
class Freezable:
|
||||
_frozen: bool = False
|
||||
|
||||
|
@ -17,7 +9,3 @@ class Freezable:
|
|||
if self._frozen:
|
||||
raise Exception("cannot modify frozen object")
|
||||
super().__setattr__(*args, **kwargs)
|
||||
|
||||
|
||||
def cache(user_function: Callable[..., _RT], /) -> Callable[..., _RT]:
|
||||
return lru_cache(maxsize=None)(user_function)
|
||||
|
|
|
@ -1 +1 @@
|
|||
#define COMMA_VERSION "0.9.7.0"
|
||||
#define COMMA_VERSION "0.9.7.1"
|
||||
|
|
|
@ -57,10 +57,6 @@ The control doesn't have to be perfect, but it should generally do what it's sup
|
|||
Get a Rivian driving with openpilot.
|
||||
Requires a merged port with lateral control and at least a POC of longitudinal control.
|
||||
|
||||
#### Toyota SecOc - $5000
|
||||
|
||||
We're contributing $5k to the [community-organized bounty](https://github.com/commaai/openpilot/discussions/19932).
|
||||
|
||||
#### Chevy Bolt with SuperCruise - $2500
|
||||
|
||||
The Bolt is already supported on the trim with standard ACC. Get openpilot working on the trim with SuperCruise. It must be a normal install: no extra pandas or other hardware, no ECU reflashes, etc. The full bounty is for a port with lateral and longitudinal control. $1500 of the bounty can be claimed with a lateral-only port.
|
||||
|
|
14
docs/CARS.md
14
docs/CARS.md
|
@ -93,7 +93,7 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||
|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 6 (with HDA II) 2023[<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">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>||
|
||||
|Hyundai|Ioniq Hybrid 2017-19|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|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 Hybrid 2017-19">Buy Here</a></sub></details>||
|
||||
|
@ -185,8 +185,8 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||
|Lexus|UX Hybrid 2019-23|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<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=Lexus&model=UX Hybrid 2019-23">Buy Here</a></sub></details>||
|
||||
|Lincoln|Aviator 2020-23|Co-Pilot360 Plus|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 Ford Q3 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=Lincoln&model=Aviator 2020-23">Buy Here</a></sub></details>||
|
||||
|Lincoln|Aviator Plug-in Hybrid 2020-23|Co-Pilot360 Plus|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 Ford Q3 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=Lincoln&model=Aviator Plug-in Hybrid 2020-23">Buy Here</a></sub></details>||
|
||||
|MAN|eTGE 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=eTGE 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|MAN|TGE 2017-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=TGE 2017-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=eTGE 2020-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|MAN|TGE 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=TGE 2017-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Mazda|CX-5 2022-24|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Mazda 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=Mazda&model=CX-5 2022-24">Buy Here</a></sub></details>||
|
||||
|Mazda|CX-9 2021-23|All|Stock|0 mph|28 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Mazda 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=Mazda&model=CX-9 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/dA3duO4a0O4" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Nissan|Altima 2019-20|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Nissan B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Nissan&model=Altima 2019-20">Buy Here</a></sub></details>||
|
||||
|
@ -237,7 +237,7 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||
|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<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=Toyota&model=Corolla Cross Hybrid (Non-US only) 2020-22">Buy Here</a></sub></details>||
|
||||
|Toyota|Corolla Hatchback 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<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=Toyota&model=Corolla Hatchback 2019-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=_66pXk0CBYA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Toyota|Corolla Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<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=Toyota&model=Corolla Hybrid 2020-22">Buy Here</a></sub></details>||
|
||||
|Toyota|Corolla Hybrid (Non-US only) 2020-23|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<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=Toyota&model=Corolla Hybrid (Non-US only) 2020-23">Buy Here</a></sub></details>||
|
||||
|Toyota|Corolla Hybrid (South America only) 2020-23|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<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=Toyota&model=Corolla Hybrid (South America only) 2020-23">Buy Here</a></sub></details>||
|
||||
|Toyota|Highlander 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<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=Toyota&model=Highlander 2017-19">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=0wS0wXSLzoo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Toyota|Highlander 2020-23|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<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=Toyota&model=Highlander 2020-23">Buy Here</a></sub></details>||
|
||||
|Toyota|Highlander Hybrid 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<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=Toyota&model=Highlander Hybrid 2017-19">Buy Here</a></sub></details>||
|
||||
|
@ -269,8 +269,8 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||
|Volkswagen|California 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=California 2021-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Caravelle 2020|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Caravelle 2020">Buy Here</a></sub></details>||
|
||||
|Volkswagen|CC 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=CC 2018-22">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Crafter 2017-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Crafter 2017-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|e-Crafter 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=e-Crafter 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Crafter 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Crafter 2017-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|e-Crafter 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=e-Crafter 2018-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|e-Golf 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=e-Golf 2014-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf 2015-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf Alltrack 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf Alltrack 2015-19">Buy Here</a></sub></details>||
|
||||
|
@ -279,7 +279,7 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||
|Volkswagen|Golf GTI 2015-21|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf GTI 2015-21">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf R 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf R 2015-19">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf SportsVan 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf SportsVan 2015-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Grand California 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Grand California 2019-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Grand California 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Grand California 2019-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Jetta 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Jetta 2018-24">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Jetta GLI 2021-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Jetta GLI 2021-24">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Passat 2015-22[<sup>10</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Passat 2015-22">Buy Here</a></sub></details>||
|
||||
|
|
|
@ -14,12 +14,12 @@ cereal
|
|||
messaging
|
||||
^^^^^^^^^
|
||||
.. autodoxygenindex::
|
||||
:project: cereal_messaging
|
||||
:project: msgq_repo_msgq
|
||||
|
||||
visionipc
|
||||
^^^^^^^^^
|
||||
.. autodoxygenindex::
|
||||
:project: cereal_visionipc
|
||||
:project: msgq_repo_msgq_visionipc
|
||||
|
||||
|
||||
selfdrive
|
||||
|
@ -77,10 +77,10 @@ sensorsd
|
|||
.. autodoxygenindex::
|
||||
:project: system_sensord_sensors
|
||||
|
||||
boardd
|
||||
pandad
|
||||
^^^^^^
|
||||
.. autodoxygenindex::
|
||||
:project: selfdrive_boardd
|
||||
:project: selfdrive_pandad
|
||||
|
||||
|
||||
rednose
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 381fc3d9dfe7d2ff40a075ff8c1f980ae2a62d19
|
2
opendbc
2
opendbc
|
@ -1 +1 @@
|
|||
Subproject commit e2906791c67eeadc9dfc3c770a678f3b888137a8
|
||||
Subproject commit e0b8c109cd3571c407cb09b5edacc223fb78be10
|
2
panda
2
panda
|
@ -1 +1 @@
|
|||
Subproject commit aaa6047409a13a9e5cd57d550e8d63a8cbab1068
|
||||
Subproject commit b1eaf465019be0b76d208a820face2a62a711a8f
|
File diff suppressed because one or more lines are too long
|
@ -20,7 +20,7 @@ markers = [
|
|||
]
|
||||
testpaths = [
|
||||
"common",
|
||||
"selfdrive/boardd",
|
||||
"selfdrive/pandad",
|
||||
"selfdrive/car",
|
||||
"selfdrive/controls",
|
||||
"selfdrive/locationd",
|
||||
|
@ -29,10 +29,9 @@ testpaths = [
|
|||
"selfdrive/test/longitudinal_maneuvers",
|
||||
"selfdrive/test/process_replay/test_fuzzy.py",
|
||||
"system/updated",
|
||||
"system/thermald",
|
||||
"system/athena",
|
||||
"system/camerad",
|
||||
"system/hardware/tici",
|
||||
"system/hardware",
|
||||
"system/loggerd",
|
||||
"system/proclogd",
|
||||
"system/tests",
|
||||
|
@ -40,7 +39,8 @@ testpaths = [
|
|||
"system/webrtc",
|
||||
"tools/lib/tests",
|
||||
"tools/replay",
|
||||
"tools/cabana"
|
||||
"tools/cabana",
|
||||
"cereal/messaging/tests",
|
||||
]
|
||||
|
||||
[tool.mypy]
|
||||
|
@ -87,34 +87,47 @@ readme = "README.md"
|
|||
repository = "https://github.com/commaai/openpilot"
|
||||
documentation = "https://docs.comma.ai"
|
||||
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "~3.11"
|
||||
|
||||
# multiple users
|
||||
sounddevice = "*" # micd + soundd
|
||||
pyserial = "*" # pigeond + qcomgpsd
|
||||
requests = "*" # many one-off uses
|
||||
sympy = "*" # rednose + friends
|
||||
crcmod = "*" # cars + qcomgpsd
|
||||
|
||||
# hardwared
|
||||
smbus2 = "*" # configuring amp
|
||||
|
||||
# core
|
||||
cffi = "*"
|
||||
scons = "*"
|
||||
pycapnp = "*"
|
||||
Cython = "*"
|
||||
numpy = "*"
|
||||
|
||||
# body / webrtcd
|
||||
aiohttp = "*"
|
||||
aiortc = "*"
|
||||
cffi = "*"
|
||||
crcmod = "*"
|
||||
Cython = "*"
|
||||
json-rpc = "*"
|
||||
pyaudio = "*"
|
||||
|
||||
# panda
|
||||
libusb1 = "*"
|
||||
numpy = "*"
|
||||
spidev = { version = "*", platform = "linux" }
|
||||
|
||||
# modeld
|
||||
onnx = ">=1.14.0"
|
||||
onnxruntime = { version = ">=1.16.3", platform = "linux", markers = "platform_machine == 'aarch64'" }
|
||||
onnxruntime-gpu = { version = ">=1.16.3", platform = "linux", markers = "platform_machine == 'x86_64'" }
|
||||
psutil = "*"
|
||||
pyaudio = "*"
|
||||
pycapnp = "*"
|
||||
pycryptodome = "*"
|
||||
PyJWT = "*"
|
||||
pyserial = "*"
|
||||
|
||||
# logging
|
||||
pyzmq = "*"
|
||||
requests = "*"
|
||||
scons = "*"
|
||||
sentry-sdk = "*"
|
||||
smbus2 = "*"
|
||||
sounddevice = "*"
|
||||
spidev = { version = "*", platform = "linux" }
|
||||
sympy = "*"
|
||||
|
||||
# athena
|
||||
PyJWT = "*"
|
||||
json-rpc = "*"
|
||||
websocket_client = "*"
|
||||
|
||||
# acados deps
|
||||
|
@ -122,9 +135,10 @@ casadi = "*"
|
|||
future-fstrings = "*"
|
||||
|
||||
# these should be removed
|
||||
markdown-it-py = "*"
|
||||
timezonefinder = "*"
|
||||
psutil = "*"
|
||||
timezonefinder = "*" # just used for nav ETA
|
||||
setproctitle = "*"
|
||||
pycryptodome = "*" # used in updated/casync, panda, body, and a test
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
av = "*"
|
||||
|
@ -152,6 +166,7 @@ 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 = "*"
|
||||
|
@ -165,6 +180,7 @@ pytest-timeout = "*"
|
|||
pytest-randomly = "*"
|
||||
pytest-asyncio = "*"
|
||||
pytest-mock = "*"
|
||||
pytest-repeat = "*"
|
||||
rerun-sdk = "*"
|
||||
ruff = "*"
|
||||
sphinx = "*"
|
||||
|
|
|
@ -105,9 +105,9 @@ git branch -m release-c3
|
|||
#cd $SOURCE_DIR
|
||||
#cp -pR -n --parents $TEST_FILES $BUILD_DIR/
|
||||
#cd $BUILD_DIR
|
||||
#RELEASE=1 selfdrive/test/test_onroad.py
|
||||
#RELEASE=1 pytest -n0 -s selfdrive/test/test_onroad.py
|
||||
#system/manager/test/test_manager.py
|
||||
#selfdrive/car/tests/test_car_interfaces.py
|
||||
#pytest selfdrive/car/tests/test_car_interfaces.py
|
||||
#rm -rf $TEST_FILES
|
||||
|
||||
if [ ! -z "$RELEASE_BRANCH" ]; then
|
||||
|
|
|
@ -10,13 +10,25 @@ ROOT = HERE + "/.."
|
|||
# - minimizing release download size
|
||||
# - keeping the diff readable
|
||||
blacklist = [
|
||||
"^scripts/",
|
||||
"body/STL/",
|
||||
"tools/cabana/",
|
||||
|
||||
"panda/drivers/",
|
||||
"panda/examples/",
|
||||
"panda/tests/safety/",
|
||||
|
||||
"opendbc/.*.dbc$",
|
||||
"opendbc/generator/",
|
||||
|
||||
"cereal/.*test.*",
|
||||
"^common/tests/",
|
||||
|
||||
# particularly large text files
|
||||
"poetry.lock",
|
||||
"third_party/catch2",
|
||||
"selfdrive/car/tests/test_models.*",
|
||||
|
||||
"^tools/",
|
||||
"^scripts/",
|
||||
"^tinygrad_repo/",
|
||||
|
||||
"matlab.*.md",
|
||||
|
@ -97,7 +109,58 @@ whitelist = [
|
|||
"tinygrad_repo/tinygrad/runtime/ops_disk.py",
|
||||
"tinygrad_repo/tinygrad/runtime/ops_gpu.py",
|
||||
"tinygrad_repo/tinygrad/shape/*",
|
||||
"tinygrad_repo/tinygrad/.*.py$",
|
||||
"tinygrad_repo/tinygrad/.*.py",
|
||||
|
||||
# TODO: do this automatically
|
||||
"opendbc/comma_body.dbc",
|
||||
"opendbc/chrysler_ram_hd_generated.dbc",
|
||||
"opendbc/chrysler_ram_dt_generated.dbc",
|
||||
"opendbc/chrysler_pacifica_2017_hybrid_generated.dbc",
|
||||
"opendbc/chrysler_pacifica_2017_hybrid_private_fusion.dbc",
|
||||
"opendbc/gm_global_a_powertrain_generated.dbc",
|
||||
"opendbc/gm_global_a_object.dbc",
|
||||
"opendbc/gm_global_a_chassis.dbc",
|
||||
"opendbc/FORD_CADS.dbc",
|
||||
"opendbc/ford_fusion_2018_adas.dbc",
|
||||
"opendbc/ford_lincoln_base_pt.dbc",
|
||||
"opendbc/honda_accord_2018_can_generated.dbc",
|
||||
"opendbc/acura_ilx_2016_can_generated.dbc",
|
||||
"opendbc/acura_rdx_2018_can_generated.dbc",
|
||||
"opendbc/acura_rdx_2020_can_generated.dbc",
|
||||
"opendbc/honda_civic_touring_2016_can_generated.dbc",
|
||||
"opendbc/honda_civic_hatchback_ex_2017_can_generated.dbc",
|
||||
"opendbc/honda_crv_touring_2016_can_generated.dbc",
|
||||
"opendbc/honda_crv_ex_2017_can_generated.dbc",
|
||||
"opendbc/honda_crv_ex_2017_body_generated.dbc",
|
||||
"opendbc/honda_crv_executive_2016_can_generated.dbc",
|
||||
"opendbc/honda_fit_ex_2018_can_generated.dbc",
|
||||
"opendbc/honda_odyssey_exl_2018_generated.dbc",
|
||||
"opendbc/honda_odyssey_extreme_edition_2018_china_can_generated.dbc",
|
||||
"opendbc/honda_insight_ex_2019_can_generated.dbc",
|
||||
"opendbc/acura_ilx_2016_nidec.dbc",
|
||||
"opendbc/honda_civic_ex_2022_can_generated.dbc",
|
||||
"opendbc/hyundai_canfd.dbc",
|
||||
"opendbc/hyundai_kia_generic.dbc",
|
||||
"opendbc/hyundai_kia_mando_front_radar_generated.dbc",
|
||||
"opendbc/mazda_2017.dbc",
|
||||
"opendbc/nissan_x_trail_2017_generated.dbc",
|
||||
"opendbc/nissan_leaf_2018_generated.dbc",
|
||||
"opendbc/subaru_global_2017_generated.dbc",
|
||||
"opendbc/subaru_global_2020_hybrid_generated.dbc",
|
||||
"opendbc/subaru_outback_2015_generated.dbc",
|
||||
"opendbc/subaru_outback_2019_generated.dbc",
|
||||
"opendbc/subaru_forester_2017_generated.dbc",
|
||||
"opendbc/toyota_tnga_k_pt_generated.dbc",
|
||||
"opendbc/toyota_new_mc_pt_generated.dbc",
|
||||
"opendbc/toyota_nodsu_pt_generated.dbc",
|
||||
"opendbc/toyota_adas.dbc",
|
||||
"opendbc/toyota_tss2_adas.dbc",
|
||||
"opendbc/vw_golf_mk4.dbc",
|
||||
"opendbc/vw_mqb_2010.dbc",
|
||||
"opendbc/tesla_can.dbc",
|
||||
"opendbc/tesla_radar_bosch_generated.dbc",
|
||||
"opendbc/tesla_radar_continental_generated.dbc",
|
||||
"opendbc/tesla_powertrain.dbc",
|
||||
]
|
||||
|
||||
# Sunnypilot whitelist
|
||||
|
@ -140,6 +203,7 @@ sunnypilot_whitelist = [
|
|||
# Merge the whitelists
|
||||
whitelist += sunnypilot_whitelist
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
for f in Path(ROOT).rglob("**/*"):
|
||||
if not (f.is_file() or f.is_symlink()):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
SConscript(['boardd/SConscript'])
|
||||
SConscript(['pandad/SConscript'])
|
||||
SConscript(['controls/lib/lateral_mpc_lib/SConscript'])
|
||||
SConscript(['controls/lib/longitudinal_mpc_lib/SConscript'])
|
||||
SConscript(['locationd/SConscript'])
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
boardd
|
||||
boardd_api_impl.cpp
|
||||
tests/test_boardd_usbprotocol
|
|
@ -1,11 +0,0 @@
|
|||
Import('env', 'envCython', 'common', 'cereal', 'messaging')
|
||||
|
||||
libs = ['usb-1.0', common, cereal, messaging, 'pthread', 'zmq', 'capnp', 'kj']
|
||||
panda = env.Library('panda', ['panda.cc', 'panda_comms.cc', 'spi.cc'])
|
||||
|
||||
env.Program('boardd', ['main.cc', 'boardd.cc'], LIBS=[panda] + libs)
|
||||
env.Library('libcan_list_to_can_capnp', ['can_list_to_can_capnp.cc'])
|
||||
|
||||
envCython.Program('boardd_api_impl.so', 'boardd_api_impl.pyx', LIBS=["can_list_to_can_capnp", 'capnp', 'kj'] + envCython["LIBS"])
|
||||
if GetOption('extras'):
|
||||
env.Program('tests/test_boardd_usbprotocol', ['tests/test_boardd_usbprotocol.cc'], LIBS=[panda] + libs)
|
|
@ -11,7 +11,7 @@ from panda import ALTERNATIVE_EXPERIENCE
|
|||
from openpilot.common.params import Params
|
||||
from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper, DT_CTRL
|
||||
|
||||
from openpilot.selfdrive.boardd.boardd import can_list_to_can_capnp
|
||||
from openpilot.selfdrive.pandad import can_list_to_can_capnp
|
||||
from openpilot.selfdrive.car.car_helpers import get_car, get_one_can
|
||||
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
|
||||
from openpilot.selfdrive.controls.lib.events import Events
|
||||
|
@ -29,8 +29,7 @@ class Car:
|
|||
self.sm = messaging.SubMaster(['pandaStates', 'carControl', 'onroadEvents'])
|
||||
self.pm = messaging.PubMaster(['sendcan', 'carState', 'carParams', 'carOutput'])
|
||||
|
||||
self.can_rcv_timeout_counter = 0 # consecutive timeout count
|
||||
self.can_rcv_cum_timeout_counter = 0 # cumulative timeout count
|
||||
self.can_rcv_cum_timeout_counter = 0
|
||||
|
||||
self.CC_prev = car.CarControl.new_message()
|
||||
self.CS_prev = car.CarState.new_message()
|
||||
|
@ -107,12 +106,7 @@ class Car:
|
|||
|
||||
# Check for CAN timeout
|
||||
if not can_rcv_valid:
|
||||
self.can_rcv_timeout_counter += 1
|
||||
self.can_rcv_cum_timeout_counter += 1
|
||||
else:
|
||||
self.can_rcv_timeout_counter = 0
|
||||
|
||||
self.can_rcv_timeout = self.can_rcv_timeout_counter >= 5
|
||||
|
||||
if can_rcv_valid and REPLAY:
|
||||
self.can_log_mono_time = messaging.log_from_bytes(can_strs[0]).logMonoTime
|
||||
|
@ -155,7 +149,6 @@ class Car:
|
|||
cs_send = messaging.new_message('carState')
|
||||
cs_send.valid = CS.canValid
|
||||
cs_send.carState = CS
|
||||
cs_send.carState.canRcvTimeout = self.can_rcv_timeout
|
||||
cs_send.carState.canErrorCounter = self.can_rcv_cum_timeout_counter
|
||||
cs_send.carState.cumLagMs = -self.rk.remaining * 1000.
|
||||
self.pm.send('carState', cs_send)
|
||||
|
@ -167,7 +160,7 @@ class Car:
|
|||
# Initialize CarInterface, once controls are ready
|
||||
# TODO: this can make us miss at least a few cycles when doing an ECU knockout
|
||||
self.CI.init(self.CP, self.can_sock, self.pm.sock['sendcan'])
|
||||
# signal boardd to switch to car safety mode
|
||||
# signal pandad to switch to car safety mode
|
||||
self.params.put_bool_nonblocking("ControlsReady", True)
|
||||
|
||||
if self.sm.all_alive(['carControl']):
|
||||
|
|
|
@ -410,6 +410,7 @@ FW_VERSIONS = {
|
|||
b'68453483AD',
|
||||
b'68453487AD',
|
||||
b'68453491AC',
|
||||
b'68453491AD',
|
||||
b'68453499AD',
|
||||
b'68453503AC',
|
||||
b'68453503AD',
|
||||
|
@ -557,6 +558,7 @@ FW_VERSIONS = {
|
|||
b'68467936AC ',
|
||||
b'68500630AD',
|
||||
b'68500630AE',
|
||||
b'68500631AE',
|
||||
b'68502719AC ',
|
||||
b'68502722AC ',
|
||||
b'68502733AC ',
|
||||
|
@ -603,6 +605,7 @@ FW_VERSIONS = {
|
|||
b'68484467AC',
|
||||
b'68484471AC',
|
||||
b'68502994AD',
|
||||
b'68502996AD',
|
||||
b'68520867AE',
|
||||
b'68520867AF',
|
||||
b'68520870AC',
|
||||
|
|
|
@ -6,7 +6,7 @@ import cereal.messaging as messaging
|
|||
from panda.python.uds import SERVICE_TYPE
|
||||
from openpilot.selfdrive.car import make_can_msg
|
||||
from openpilot.selfdrive.car.fw_query_definitions import EcuAddrBusType
|
||||
from openpilot.selfdrive.boardd.boardd import can_list_to_can_capnp
|
||||
from openpilot.selfdrive.pandad import can_list_to_can_capnp
|
||||
from openpilot.common.swaglog import cloudlog
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
import random
|
||||
from collections.abc import Iterable
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ class Request:
|
|||
auxiliary: bool = False
|
||||
# FW responses from these queries will not be used for fingerprinting
|
||||
logging: bool = False
|
||||
# boardd toggles OBD multiplexing on/off as needed
|
||||
# pandad toggles OBD multiplexing on/off as needed
|
||||
obd_multiplexing: bool = True
|
||||
|
||||
|
||||
|
|
|
@ -352,7 +352,7 @@ if __name__ == "__main__":
|
|||
pandaStates_sock = messaging.sub_sock('pandaStates')
|
||||
sendcan = messaging.pub_sock('sendcan')
|
||||
|
||||
# Set up params for boardd
|
||||
# Set up params for pandad
|
||||
params = Params()
|
||||
params.remove("FirmwareQueryDone")
|
||||
params.put_bool("IsOnroad", False)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
from parameterized import parameterized
|
||||
|
||||
from openpilot.selfdrive.car.gm.fingerprints import FINGERPRINTS
|
||||
|
|
|
@ -11,43 +11,6 @@ Ecu = car.CarParams.Ecu
|
|||
|
||||
FW_VERSIONS = {
|
||||
CAR.HONDA_ACCORD: {
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-6A0-8720\x00\x00',
|
||||
b'37805-6A0-9520\x00\x00',
|
||||
b'37805-6A0-9620\x00\x00',
|
||||
b'37805-6A0-9720\x00\x00',
|
||||
b'37805-6A0-A540\x00\x00',
|
||||
b'37805-6A0-A550\x00\x00',
|
||||
b'37805-6A0-A640\x00\x00',
|
||||
b'37805-6A0-A650\x00\x00',
|
||||
b'37805-6A0-A740\x00\x00',
|
||||
b'37805-6A0-A750\x00\x00',
|
||||
b'37805-6A0-A840\x00\x00',
|
||||
b'37805-6A0-A850\x00\x00',
|
||||
b'37805-6A0-A930\x00\x00',
|
||||
b'37805-6A0-AF30\x00\x00',
|
||||
b'37805-6A0-AG30\x00\x00',
|
||||
b'37805-6A0-AJ10\x00\x00',
|
||||
b'37805-6A0-C540\x00\x00',
|
||||
b'37805-6A0-CG20\x00\x00',
|
||||
b'37805-6A1-H650\x00\x00',
|
||||
b'37805-6B2-A550\x00\x00',
|
||||
b'37805-6B2-A560\x00\x00',
|
||||
b'37805-6B2-A650\x00\x00',
|
||||
b'37805-6B2-A660\x00\x00',
|
||||
b'37805-6B2-A720\x00\x00',
|
||||
b'37805-6B2-A810\x00\x00',
|
||||
b'37805-6B2-A820\x00\x00',
|
||||
b'37805-6B2-A920\x00\x00',
|
||||
b'37805-6B2-A960\x00\x00',
|
||||
b'37805-6B2-AA10\x00\x00',
|
||||
b'37805-6B2-C520\x00\x00',
|
||||
b'37805-6B2-C540\x00\x00',
|
||||
b'37805-6B2-C560\x00\x00',
|
||||
b'37805-6B2-M520\x00\x00',
|
||||
b'37805-6B2-Y810\x00\x00',
|
||||
b'37805-6M4-B730\x00\x00',
|
||||
],
|
||||
(Ecu.shiftByWire, 0x18da0bf1, None): [
|
||||
b'54008-TVC-A910\x00\x00',
|
||||
b'54008-TWA-A910\x00\x00',
|
||||
|
@ -175,38 +138,6 @@ FW_VERSIONS = {
|
|||
],
|
||||
},
|
||||
CAR.HONDA_CIVIC: {
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-5AA-A640\x00\x00',
|
||||
b'37805-5AA-A650\x00\x00',
|
||||
b'37805-5AA-A670\x00\x00',
|
||||
b'37805-5AA-A680\x00\x00',
|
||||
b'37805-5AA-A810\x00\x00',
|
||||
b'37805-5AA-C640\x00\x00',
|
||||
b'37805-5AA-C680\x00\x00',
|
||||
b'37805-5AA-C820\x00\x00',
|
||||
b'37805-5AA-L650\x00\x00',
|
||||
b'37805-5AA-L660\x00\x00',
|
||||
b'37805-5AA-L680\x00\x00',
|
||||
b'37805-5AA-L690\x00\x00',
|
||||
b'37805-5AA-L810\x00\x00',
|
||||
b'37805-5AG-Q710\x00\x00',
|
||||
b'37805-5AJ-A610\x00\x00',
|
||||
b'37805-5AJ-A620\x00\x00',
|
||||
b'37805-5AJ-L610\x00\x00',
|
||||
b'37805-5BA-A310\x00\x00',
|
||||
b'37805-5BA-A510\x00\x00',
|
||||
b'37805-5BA-A740\x00\x00',
|
||||
b'37805-5BA-A760\x00\x00',
|
||||
b'37805-5BA-A930\x00\x00',
|
||||
b'37805-5BA-A960\x00\x00',
|
||||
b'37805-5BA-C640\x00\x00',
|
||||
b'37805-5BA-C860\x00\x00',
|
||||
b'37805-5BA-L410\x00\x00',
|
||||
b'37805-5BA-L760\x00\x00',
|
||||
b'37805-5BA-L930\x00\x00',
|
||||
b'37805-5BA-L940\x00\x00',
|
||||
b'37805-5BA-L960\x00\x00',
|
||||
],
|
||||
(Ecu.transmission, 0x18da1ef1, None): [
|
||||
b'28101-5CG-A040\x00\x00',
|
||||
b'28101-5CG-A050\x00\x00',
|
||||
|
@ -256,61 +187,6 @@ FW_VERSIONS = {
|
|||
],
|
||||
},
|
||||
CAR.HONDA_CIVIC_BOSCH: {
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-5AA-A940\x00\x00',
|
||||
b'37805-5AA-A950\x00\x00',
|
||||
b'37805-5AA-C950\x00\x00',
|
||||
b'37805-5AA-L940\x00\x00',
|
||||
b'37805-5AA-L950\x00\x00',
|
||||
b'37805-5AG-Z910\x00\x00',
|
||||
b'37805-5AJ-A750\x00\x00',
|
||||
b'37805-5AJ-L750\x00\x00',
|
||||
b'37805-5AK-T530\x00\x00',
|
||||
b'37805-5AN-A750\x00\x00',
|
||||
b'37805-5AN-A830\x00\x00',
|
||||
b'37805-5AN-A840\x00\x00',
|
||||
b'37805-5AN-A930\x00\x00',
|
||||
b'37805-5AN-A940\x00\x00',
|
||||
b'37805-5AN-A950\x00\x00',
|
||||
b'37805-5AN-AG20\x00\x00',
|
||||
b'37805-5AN-AH20\x00\x00',
|
||||
b'37805-5AN-AJ30\x00\x00',
|
||||
b'37805-5AN-AK10\x00\x00',
|
||||
b'37805-5AN-AK20\x00\x00',
|
||||
b'37805-5AN-AR10\x00\x00',
|
||||
b'37805-5AN-AR20\x00\x00',
|
||||
b'37805-5AN-C650\x00\x00',
|
||||
b'37805-5AN-CH20\x00\x00',
|
||||
b'37805-5AN-E630\x00\x00',
|
||||
b'37805-5AN-E720\x00\x00',
|
||||
b'37805-5AN-E820\x00\x00',
|
||||
b'37805-5AN-J820\x00\x00',
|
||||
b'37805-5AN-L840\x00\x00',
|
||||
b'37805-5AN-L930\x00\x00',
|
||||
b'37805-5AN-L940\x00\x00',
|
||||
b'37805-5AN-LF20\x00\x00',
|
||||
b'37805-5AN-LH20\x00\x00',
|
||||
b'37805-5AN-LJ20\x00\x00',
|
||||
b'37805-5AN-LR20\x00\x00',
|
||||
b'37805-5AN-LS20\x00\x00',
|
||||
b'37805-5AW-G720\x00\x00',
|
||||
b'37805-5AZ-E850\x00\x00',
|
||||
b'37805-5AZ-G540\x00\x00',
|
||||
b'37805-5AZ-G740\x00\x00',
|
||||
b'37805-5AZ-G840\x00\x00',
|
||||
b'37805-5BB-A530\x00\x00',
|
||||
b'37805-5BB-A540\x00\x00',
|
||||
b'37805-5BB-A620\x00\x00',
|
||||
b'37805-5BB-A630\x00\x00',
|
||||
b'37805-5BB-A640\x00\x00',
|
||||
b'37805-5BB-C540\x00\x00',
|
||||
b'37805-5BB-C630\x00\x00',
|
||||
b'37805-5BB-C640\x00\x00',
|
||||
b'37805-5BB-L540\x00\x00',
|
||||
b'37805-5BB-L630\x00\x00',
|
||||
b'37805-5BB-L640\x00\x00',
|
||||
b'37805-5BF-J130\x00\x00',
|
||||
],
|
||||
(Ecu.transmission, 0x18da1ef1, None): [
|
||||
b'28101-5CG-A920\x00\x00',
|
||||
b'28101-5CG-AB10\x00\x00',
|
||||
|
@ -422,10 +298,6 @@ FW_VERSIONS = {
|
|||
],
|
||||
},
|
||||
CAR.HONDA_CIVIC_BOSCH_DIESEL: {
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-59N-G630\x00\x00',
|
||||
b'37805-59N-G830\x00\x00',
|
||||
],
|
||||
(Ecu.transmission, 0x18da1ef1, None): [
|
||||
b'28101-59Y-G220\x00\x00',
|
||||
b'28101-59Y-G620\x00\x00',
|
||||
|
@ -496,41 +368,6 @@ FW_VERSIONS = {
|
|||
],
|
||||
},
|
||||
CAR.HONDA_CRV_5G: {
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-5PA-3060\x00\x00',
|
||||
b'37805-5PA-3080\x00\x00',
|
||||
b'37805-5PA-3180\x00\x00',
|
||||
b'37805-5PA-4050\x00\x00',
|
||||
b'37805-5PA-4150\x00\x00',
|
||||
b'37805-5PA-6520\x00\x00',
|
||||
b'37805-5PA-6530\x00\x00',
|
||||
b'37805-5PA-6630\x00\x00',
|
||||
b'37805-5PA-6640\x00\x00',
|
||||
b'37805-5PA-7630\x00\x00',
|
||||
b'37805-5PA-9530\x00\x00',
|
||||
b'37805-5PA-9630\x00\x00',
|
||||
b'37805-5PA-9640\x00\x00',
|
||||
b'37805-5PA-9730\x00\x00',
|
||||
b'37805-5PA-9830\x00\x00',
|
||||
b'37805-5PA-9840\x00\x00',
|
||||
b'37805-5PA-A650\x00\x00',
|
||||
b'37805-5PA-A670\x00\x00',
|
||||
b'37805-5PA-A680\x00\x00',
|
||||
b'37805-5PA-A850\x00\x00',
|
||||
b'37805-5PA-A870\x00\x00',
|
||||
b'37805-5PA-A880\x00\x00',
|
||||
b'37805-5PA-A890\x00\x00',
|
||||
b'37805-5PA-AB10\x00\x00',
|
||||
b'37805-5PA-AD10\x00\x00',
|
||||
b'37805-5PA-AF20\x00\x00',
|
||||
b'37805-5PA-AF30\x00\x00',
|
||||
b'37805-5PA-AH20\x00\x00',
|
||||
b'37805-5PA-BF10\x00\x00',
|
||||
b'37805-5PA-C680\x00\x00',
|
||||
b'37805-5PD-Q630\x00\x00',
|
||||
b'37805-5PF-F730\x00\x00',
|
||||
b'37805-5PF-M630\x00\x00',
|
||||
],
|
||||
(Ecu.transmission, 0x18da1ef1, None): [
|
||||
b'28101-5RG-A020\x00\x00',
|
||||
b'28101-5RG-A030\x00\x00',
|
||||
|
@ -606,10 +443,6 @@ FW_VERSIONS = {
|
|||
],
|
||||
},
|
||||
CAR.HONDA_CRV_EU: {
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-R5Z-G740\x00\x00',
|
||||
b'37805-R5Z-G780\x00\x00',
|
||||
],
|
||||
(Ecu.vsa, 0x18da28f1, None): [
|
||||
b'57114-T1V-G920\x00\x00',
|
||||
],
|
||||
|
@ -710,24 +543,6 @@ FW_VERSIONS = {
|
|||
b'38897-THR-A010\x00\x00',
|
||||
b'38897-THR-A020\x00\x00',
|
||||
],
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-5MR-3050\x00\x00',
|
||||
b'37805-5MR-3150\x00\x00',
|
||||
b'37805-5MR-3250\x00\x00',
|
||||
b'37805-5MR-4070\x00\x00',
|
||||
b'37805-5MR-4080\x00\x00',
|
||||
b'37805-5MR-4170\x00\x00',
|
||||
b'37805-5MR-4180\x00\x00',
|
||||
b'37805-5MR-A240\x00\x00',
|
||||
b'37805-5MR-A250\x00\x00',
|
||||
b'37805-5MR-A310\x00\x00',
|
||||
b'37805-5MR-A740\x00\x00',
|
||||
b'37805-5MR-A750\x00\x00',
|
||||
b'37805-5MR-A840\x00\x00',
|
||||
b'37805-5MR-C620\x00\x00',
|
||||
b'37805-5MR-D530\x00\x00',
|
||||
b'37805-5MR-K730\x00\x00',
|
||||
],
|
||||
(Ecu.eps, 0x18da30f1, None): [
|
||||
b'39990-THR-A020\x00\x00',
|
||||
b'39990-THR-A030\x00\x00',
|
||||
|
@ -812,39 +627,6 @@ FW_VERSIONS = {
|
|||
b'28101-5EZ-A700\x00\x00',
|
||||
b'28103-5EY-A110\x00\x00',
|
||||
],
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-RLV-4060\x00\x00',
|
||||
b'37805-RLV-4070\x00\x00',
|
||||
b'37805-RLV-5140\x00\x00',
|
||||
b'37805-RLV-5230\x00\x00',
|
||||
b'37805-RLV-5250\x00\x00',
|
||||
b'37805-RLV-A630\x00\x00',
|
||||
b'37805-RLV-A830\x00\x00',
|
||||
b'37805-RLV-A840\x00\x00',
|
||||
b'37805-RLV-B210\x00\x00',
|
||||
b'37805-RLV-B220\x00\x00',
|
||||
b'37805-RLV-B420\x00\x00',
|
||||
b'37805-RLV-B430\x00\x00',
|
||||
b'37805-RLV-B620\x00\x00',
|
||||
b'37805-RLV-B710\x00\x00',
|
||||
b'37805-RLV-B720\x00\x00',
|
||||
b'37805-RLV-C430\x00\x00',
|
||||
b'37805-RLV-C510\x00\x00',
|
||||
b'37805-RLV-C520\x00\x00',
|
||||
b'37805-RLV-C530\x00\x00',
|
||||
b'37805-RLV-C910\x00\x00',
|
||||
b'37805-RLV-F120\x00\x00',
|
||||
b'37805-RLV-L080\x00\x00',
|
||||
b'37805-RLV-L090\x00\x00',
|
||||
b'37805-RLV-L150\x00\x00',
|
||||
b'37805-RLV-L160\x00\x00',
|
||||
b'37805-RLV-L180\x00\x00',
|
||||
b'37805-RLV-L350\x00\x00',
|
||||
b'37805-RLV-L410\x00\x00',
|
||||
b'37805-RLV-L430\x00\x00',
|
||||
b'37805-RLV-L830\x00\x00',
|
||||
b'37805-RLV-L850\x00\x00',
|
||||
],
|
||||
(Ecu.gateway, 0x18daeff1, None): [
|
||||
b'38897-TG7-A030\x00\x00',
|
||||
b'38897-TG7-A040\x00\x00',
|
||||
|
@ -922,26 +704,6 @@ FW_VERSIONS = {
|
|||
],
|
||||
},
|
||||
CAR.ACURA_RDX_3G: {
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-5YF-A130\x00\x00',
|
||||
b'37805-5YF-A230\x00\x00',
|
||||
b'37805-5YF-A320\x00\x00',
|
||||
b'37805-5YF-A330\x00\x00',
|
||||
b'37805-5YF-A420\x00\x00',
|
||||
b'37805-5YF-A430\x00\x00',
|
||||
b'37805-5YF-A750\x00\x00',
|
||||
b'37805-5YF-A760\x00\x00',
|
||||
b'37805-5YF-A770\x00\x00',
|
||||
b'37805-5YF-A850\x00\x00',
|
||||
b'37805-5YF-A860\x00\x00',
|
||||
b'37805-5YF-A870\x00\x00',
|
||||
b'37805-5YF-AD20\x00\x00',
|
||||
b'37805-5YF-C210\x00\x00',
|
||||
b'37805-5YF-C220\x00\x00',
|
||||
b'37805-5YF-C410\x00\x00',
|
||||
b'37805-5YF-C420\x00\x00',
|
||||
b'37805-5YF-C430\x00\x00',
|
||||
],
|
||||
(Ecu.vsa, 0x18da28f1, None): [
|
||||
b'57114-TJB-A030\x00\x00',
|
||||
b'57114-TJB-A040\x00\x00',
|
||||
|
@ -1096,10 +858,6 @@ FW_VERSIONS = {
|
|||
b'28101-6EH-A010\x00\x00',
|
||||
b'28101-6JC-M310\x00\x00',
|
||||
],
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-6CT-A710\x00\x00',
|
||||
b'37805-6HZ-M630\x00\x00',
|
||||
],
|
||||
(Ecu.electricBrakeBooster, 0x18da2bf1, None): [
|
||||
b'46114-3W0-A020\x00\x00',
|
||||
],
|
||||
|
@ -1180,14 +938,5 @@ FW_VERSIONS = {
|
|||
b'28101-65H-A120\x00\x00',
|
||||
b'28101-65J-N010\x00\x00',
|
||||
],
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-64A-A540\x00\x00',
|
||||
b'37805-64A-A620\x00\x00',
|
||||
b'37805-64D-P510\x00\x00',
|
||||
b'37805-64L-A540\x00\x00',
|
||||
b'37805-64S-A540\x00\x00',
|
||||
b'37805-64S-A720\x00\x00',
|
||||
b'37805-64S-AA10\x00\x00',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
import re
|
||||
|
||||
from openpilot.selfdrive.car.honda.fingerprints import FW_VERSIONS
|
||||
|
|
|
@ -318,6 +318,7 @@ FW_QUERY_CONFIG = FwQueryConfig(
|
|||
],
|
||||
# We lose these ECUs without the comma power on these cars.
|
||||
# Note that we still attempt to match with them when they are present
|
||||
# This is or'd with (ALL_ECUS - ESSENTIAL_ECUS) from fw_versions.py
|
||||
non_essential_ecus={
|
||||
Ecu.eps: [CAR.ACURA_RDX_3G, CAR.HONDA_ACCORD, CAR.HONDA_CIVIC_2022, CAR.HONDA_E, CAR.HONDA_HRV_3G],
|
||||
Ecu.vsa: [CAR.ACURA_RDX_3G, CAR.HONDA_ACCORD, CAR.HONDA_CIVIC, CAR.HONDA_CIVIC_BOSCH, CAR.HONDA_CIVIC_2022, CAR.HONDA_CRV_5G, CAR.HONDA_CRV_HYBRID,
|
||||
|
@ -325,6 +326,7 @@ FW_QUERY_CONFIG = FwQueryConfig(
|
|||
},
|
||||
extra_ecus=[
|
||||
(Ecu.combinationMeter, 0x18da60f1, None),
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None),
|
||||
# The only other ECU on PT bus accessible by camera on radarless Civic
|
||||
# This is likely a manufacturer-specific sub-address implementation: the camera responds to this and 0x18dab0f1
|
||||
# Unclear what the part number refers to: 8S103 is 'Camera Set Mono', while 36160 is 'Camera Monocular - Honda'
|
||||
|
|
|
@ -23,9 +23,6 @@ FINGERPRINTS = {
|
|||
CAR.GENESIS_G90: [{
|
||||
67: 8, 68: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 358: 6, 359: 8, 544: 8, 593: 8, 608: 8, 688: 5, 809: 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1162: 4, 1168: 7, 1170: 8, 1173: 8, 1184: 8, 1265: 4, 1280: 1, 1281: 3, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1370: 8, 1371: 8, 1378: 4, 1384: 8, 1407: 8, 1419: 8, 1425: 2, 1427: 6, 1434: 2, 1456: 4, 1470: 8, 1988: 8, 2000: 8, 2003: 8, 2004: 8, 2005: 8, 2008: 8, 2011: 8, 2012: 8, 2013: 8
|
||||
}],
|
||||
CAR.HYUNDAI_IONIQ_EV_2020: [{
|
||||
127: 8, 304: 8, 320: 8, 339: 8, 352: 8, 356: 4, 524: 8, 544: 7, 593: 8, 688: 5, 832: 8, 881: 8, 882: 8, 897: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1078: 4, 1136: 8, 1151: 6, 1155: 8, 1156: 8, 1157: 4, 1164: 8, 1168: 7, 1173: 8, 1183: 8, 1186: 2, 1191: 2, 1225: 8, 1265: 4, 1280: 1, 1287: 4, 1290: 8, 1291: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1355: 8, 1363: 8, 1369: 8, 1379: 8, 1407: 8, 1419: 8, 1426: 8, 1427: 6, 1429: 8, 1430: 8, 1456: 4, 1470: 8, 1473: 8, 1507: 8, 1535: 8, 1988: 8, 1996: 8, 2000: 8, 2004: 8, 2005: 8, 2008: 8, 2012: 8, 2013: 8
|
||||
}],
|
||||
CAR.HYUNDAI_KONA_EV: [{
|
||||
127: 8, 304: 8, 320: 8, 339: 8, 352: 8, 356: 4, 544: 8, 549: 8, 593: 8, 688: 5, 832: 8, 881: 8, 882: 8, 897: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1078: 4, 1136: 8, 1151: 6, 1168: 7, 1173: 8, 1183: 8, 1186: 2, 1191: 2, 1225: 8, 1265: 4, 1280: 1, 1287: 4, 1290: 8, 1291: 8, 1292: 8, 1294: 8, 1307: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1355: 8, 1363: 8, 1369: 8, 1378: 4, 1407: 8, 1419: 8, 1426: 8, 1427: 6, 1429: 8, 1430: 8, 1456: 4, 1470: 8, 1473: 8, 1507: 8, 1535: 8, 2000: 8, 2004: 8, 2008: 8, 2012: 8, 1157: 4, 1193: 8, 1379: 8, 1988: 8, 1996: 8
|
||||
}],
|
||||
|
@ -135,9 +132,12 @@ FW_VERSIONS = {
|
|||
b'\xf1\x00AEev SCC F-CUP 1.00 1.00 99110-G7200 ',
|
||||
b'\xf1\x00AEev SCC F-CUP 1.00 1.00 99110-G7500 ',
|
||||
b'\xf1\x00AEev SCC F-CUP 1.00 1.01 99110-G7000 ',
|
||||
b'\xf1\x00AEev SCC F-CUP 1.00 1.01 99110-G7100 ',
|
||||
b'\xf1\x00AEev SCC FHCUP 1.00 1.01 99110-G7100 ',
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00AE MDPS C 1.00 1.01 56310/G7310 4APEC101',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.01 56310/G7510 4APEC101',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.01 56310/G7560 4APEC101',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
|
@ -146,6 +146,7 @@ FW_VERSIONS = {
|
|||
b'\xf1\x00AEE MFC AT EUR LHD 1.00 1.01 95740-G2600 190819',
|
||||
b'\xf1\x00AEE MFC AT EUR LHD 1.00 1.03 95740-G2500 190516',
|
||||
b'\xf1\x00AEE MFC AT EUR RHD 1.00 1.01 95740-G2600 190819',
|
||||
b'\xf1\x00AEE MFC AT USA LHD 1.00 1.01 95740-G2600 190819',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_IONIQ_EV_LTD: {
|
||||
|
@ -749,6 +750,7 @@ FW_VERSIONS = {
|
|||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00DEhe SCC F-CUP 1.00 1.00 99110-G5600 ',
|
||||
b'\xf1\x00DEhe SCC FHCUP 1.00 1.00 99110-G5600 ',
|
||||
],
|
||||
},
|
||||
CAR.KIA_NIRO_HEV_2021: {
|
||||
|
@ -877,6 +879,7 @@ FW_VERSIONS = {
|
|||
b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.03 99210-AA000 200819',
|
||||
b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.03 99210-AB000 220426',
|
||||
b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.06 99210-AA000 220111',
|
||||
b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.07 99210-AA000 220426',
|
||||
b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.08 99210-AA000 220728',
|
||||
],
|
||||
(Ecu.abs, 0x7d1, None): [
|
||||
|
@ -1001,6 +1004,7 @@ FW_VERSIONS = {
|
|||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00CE MFC AT CAN LHD 1.00 1.04 99211-KL000 221213',
|
||||
b'\xf1\x00CE MFC AT EUR LHD 1.00 1.03 99211-KL000 221011',
|
||||
b'\xf1\x00CE MFC AT EUR LHD 1.00 1.04 99211-KL000 221213',
|
||||
b'\xf1\x00CE MFC AT USA LHD 1.00 1.04 99211-KL000 221213',
|
||||
],
|
||||
},
|
||||
|
@ -1039,10 +1043,10 @@ FW_VERSIONS = {
|
|||
CAR.KIA_SPORTAGE_5TH_GEN: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00NQ5 FR_CMR AT AUS RHD 1.00 1.00 99211-P1040 663',
|
||||
b'\xf1\x00NQ5 FR_CMR AT EUR LHD 1.00 1.00 99211-P1040 663',
|
||||
b'\xf1\x00NQ5 FR_CMR AT GEN LHD 1.00 1.00 99211-P1060 665',
|
||||
b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1030 662',
|
||||
b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1040 663',
|
||||
b'\xf1\x00NQ5 FR_CMR AT EUR LHD 1.00 1.00 99211-P1040 663',
|
||||
b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1060 665',
|
||||
b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1070 690',
|
||||
],
|
||||
|
|
|
@ -86,6 +86,9 @@ class CarInterface(CarInterfaceBase):
|
|||
ret.steerLimitTimer = 0.4
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
|
||||
if candidate == CAR.KIA_OPTIMA_G4_FL:
|
||||
ret.steerActuatorDelay = 0.2
|
||||
|
||||
# *** longitudinal control ***
|
||||
if candidate in CANFD_CAR:
|
||||
ret.longitudinalTuning.kpV = [0.1]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
from hypothesis import settings, given, strategies as st
|
||||
|
||||
import pytest
|
||||
|
|
|
@ -328,7 +328,7 @@ class CAR(Platforms):
|
|||
flags=HyundaiFlags.EV,
|
||||
)
|
||||
HYUNDAI_IONIQ_6 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Ioniq 6 (with HDA II) 2023", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_p]))],
|
||||
[HyundaiCarDocs("Hyundai Ioniq 6 (with HDA II) 2023-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_p]))],
|
||||
HYUNDAI_IONIQ_5.specs,
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE,
|
||||
)
|
||||
|
@ -529,7 +529,7 @@ class CAR(Platforms):
|
|||
# TODO: From 3.3T Sport Advanced 2022 & Prestige 2023 Trim, 2.0T is unknown
|
||||
HyundaiCarDocs("Genesis G70 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_l])),
|
||||
],
|
||||
CarSpecs(mass=3673 * CV.LB_TO_KG, wheelbase=2.83, steerRatio=12.9),
|
||||
GENESIS_G70.specs,
|
||||
flags=HyundaiFlags.MANDO_RADAR,
|
||||
)
|
||||
GENESIS_GV70_1ST_GEN = HyundaiCanFDPlatformConfig(
|
||||
|
|
|
@ -48,6 +48,18 @@ FORWARD_GEARS = [GearShifter.drive, GearShifter.low, GearShifter.eco,
|
|||
def similarity(s1: str, s2: str) -> float:
|
||||
return SequenceMatcher(None, s1, s2).ratio()
|
||||
|
||||
GEAR_SHIFTER_MAP: dict[str, car.CarState.GearShifter] = {
|
||||
'P': GearShifter.park, 'PARK': GearShifter.park,
|
||||
'R': GearShifter.reverse, 'REVERSE': GearShifter.reverse,
|
||||
'N': GearShifter.neutral, 'NEUTRAL': GearShifter.neutral,
|
||||
'E': GearShifter.eco, 'ECO': GearShifter.eco,
|
||||
'T': GearShifter.manumatic, 'MANUAL': GearShifter.manumatic,
|
||||
'D': GearShifter.drive, 'DRIVE': GearShifter.drive,
|
||||
'S': GearShifter.sport, 'SPORT': GearShifter.sport,
|
||||
'L': GearShifter.low, 'LOW': GearShifter.low,
|
||||
'B': GearShifter.brake, 'BRAKE': GearShifter.brake,
|
||||
}
|
||||
|
||||
|
||||
class LatControlInputs(NamedTuple):
|
||||
lateral_acceleration: float
|
||||
|
@ -60,29 +72,33 @@ TorqueFromLateralAccelCallbackType = Callable[[LatControlInputs, car.CarParams.L
|
|||
|
||||
|
||||
@cache
|
||||
def get_torque_params(candidate):
|
||||
def get_torque_params():
|
||||
with open(TORQUE_SUBSTITUTE_PATH, 'rb') as f:
|
||||
sub = tomllib.load(f)
|
||||
if candidate in sub:
|
||||
candidate = sub[candidate]
|
||||
|
||||
with open(TORQUE_PARAMS_PATH, 'rb') as f:
|
||||
params = tomllib.load(f)
|
||||
with open(TORQUE_OVERRIDE_PATH, 'rb') as f:
|
||||
override = tomllib.load(f)
|
||||
|
||||
# Ensure no overlap
|
||||
if sum([candidate in x for x in [sub, params, override]]) > 1:
|
||||
raise RuntimeError(f'{candidate} is defined twice in torque config')
|
||||
torque_params = {}
|
||||
for candidate in (sub.keys() | params.keys() | override.keys()) - {'legend'}:
|
||||
if sum([candidate in x for x in [sub, params, override]]) > 1:
|
||||
raise RuntimeError(f'{candidate} is defined twice in torque config')
|
||||
|
||||
if candidate in override:
|
||||
out = override[candidate]
|
||||
elif candidate in params:
|
||||
out = params[candidate]
|
||||
else:
|
||||
raise NotImplementedError(f"Did not find torque params for {candidate}")
|
||||
return {key: out[i] for i, key in enumerate(params['legend'])}
|
||||
sub_candidate = sub.get(candidate, candidate)
|
||||
|
||||
if sub_candidate in override:
|
||||
out = override[sub_candidate]
|
||||
elif sub_candidate in params:
|
||||
out = params[sub_candidate]
|
||||
else:
|
||||
raise NotImplementedError(f"Did not find torque params for {sub_candidate}")
|
||||
|
||||
torque_params[sub_candidate] = {key: out[i] for i, key in enumerate(params['legend'])}
|
||||
if candidate in sub:
|
||||
torque_params[candidate] = torque_params[sub_candidate]
|
||||
|
||||
return torque_params
|
||||
|
||||
# lateral neural network feedforward
|
||||
class FluxModel:
|
||||
|
@ -344,7 +360,7 @@ class CarInterfaceBase(ABC):
|
|||
ret.carFingerprint = candidate
|
||||
|
||||
# Car docs fields
|
||||
ret.maxLateralAccel = get_torque_params(candidate)['MAX_LAT_ACCEL_MEASURED']
|
||||
ret.maxLateralAccel = get_torque_params()[candidate]['MAX_LAT_ACCEL_MEASURED']
|
||||
ret.autoResumeSng = True # describes whether car can resume from a stop automatically
|
||||
|
||||
# standard ALC params
|
||||
|
@ -378,7 +394,7 @@ class CarInterfaceBase(ABC):
|
|||
|
||||
@staticmethod
|
||||
def configure_torque_tune(candidate, tune, steering_angle_deadzone_deg=0.0, use_steering_angle=True):
|
||||
params = get_torque_params(candidate)
|
||||
params = get_torque_params()[candidate]
|
||||
|
||||
tune.init('torque')
|
||||
tune.torque.useSteeringAngle = use_steering_angle
|
||||
|
@ -840,19 +856,7 @@ class CarStateBase(ABC):
|
|||
def parse_gear_shifter(gear: str | None) -> car.CarState.GearShifter:
|
||||
if gear is None:
|
||||
return GearShifter.unknown
|
||||
|
||||
d: dict[str, car.CarState.GearShifter] = {
|
||||
'P': GearShifter.park, 'PARK': GearShifter.park,
|
||||
'R': GearShifter.reverse, 'REVERSE': GearShifter.reverse,
|
||||
'N': GearShifter.neutral, 'NEUTRAL': GearShifter.neutral,
|
||||
'E': GearShifter.eco, 'ECO': GearShifter.eco,
|
||||
'T': GearShifter.manumatic, 'MANUAL': GearShifter.manumatic,
|
||||
'D': GearShifter.drive, 'DRIVE': GearShifter.drive,
|
||||
'S': GearShifter.sport, 'SPORT': GearShifter.sport,
|
||||
'L': GearShifter.low, 'LOW': GearShifter.low,
|
||||
'B': GearShifter.brake, 'BRAKE': GearShifter.brake,
|
||||
}
|
||||
return d.get(gear.upper(), GearShifter.unknown)
|
||||
return GEAR_SHIFTER_MAP.get(gear.upper(), GearShifter.unknown)
|
||||
|
||||
@staticmethod
|
||||
def get_can_parser(CP):
|
||||
|
|
|
@ -4,7 +4,7 @@ from functools import partial
|
|||
|
||||
import cereal.messaging as messaging
|
||||
from openpilot.common.swaglog import cloudlog
|
||||
from openpilot.selfdrive.boardd.boardd import can_list_to_can_capnp
|
||||
from openpilot.selfdrive.pandad import can_list_to_can_capnp
|
||||
from openpilot.selfdrive.car.fw_query_definitions import AddrType
|
||||
from panda.python.uds import CanClient, IsoTpMessage, FUNCTIONAL_ADDRS, get_rx_addr_for_tx_addr
|
||||
|
||||
|
|
|
@ -311,6 +311,7 @@ FW_VERSIONS = {
|
|||
b'\x00\x00d\xd3\x1f@ \t',
|
||||
],
|
||||
(Ecu.engine, 0x7e0, None): [
|
||||
b'\xa7"@0\x07',
|
||||
b'\xa7"@p\x07',
|
||||
b'\xa7)\xa0q\x07',
|
||||
b'\xba"@@\x07',
|
||||
|
@ -318,6 +319,7 @@ FW_VERSIONS = {
|
|||
],
|
||||
(Ecu.transmission, 0x7e1, None): [
|
||||
b'\x1a\xf6F`\x00',
|
||||
b'\xda\xf2`p\x00',
|
||||
b'\xda\xf2`\x80\x00',
|
||||
b'\xda\xfd\xe0\x80\x00',
|
||||
b'\xdc\xf2@`\x00',
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
from parameterized import parameterized
|
||||
|
||||
from cereal import log, messaging
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import math
|
||||
import hypothesis.strategies as st
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
from collections import defaultdict
|
||||
import os
|
||||
import pytest
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
|
||||
from openpilot.common.basedir import BASEDIR
|
||||
|
||||
# messages reserved for CAN based ignition (see can_ignition_hook function in panda/board/drivers/can)
|
||||
# (addr, len)
|
||||
CAN_IGNITION_MSGS = {
|
||||
'gm': [(0x1F1, 8), (0x160, 5)],
|
||||
#'tesla' : [(0x348, 8)],
|
||||
}
|
||||
|
||||
def _get_fingerprints():
|
||||
# read all the folders in selfdrive/car and return a dict where:
|
||||
# - keys are all the car names that which we have a fingerprint dict for
|
||||
# - values are dicts of fingeprints for each trim
|
||||
fingerprints = {}
|
||||
for car_folder in [x[0] for x in os.walk(BASEDIR + '/selfdrive/car')]:
|
||||
car_name = car_folder.split('/')[-1]
|
||||
try:
|
||||
fingerprints[car_name] = __import__(f'selfdrive.car.{car_name}.values', fromlist=['FINGERPRINTS']).FINGERPRINTS
|
||||
except (ImportError, OSError, AttributeError):
|
||||
pass
|
||||
|
||||
return fingerprints
|
||||
|
||||
|
||||
def check_fingerprint_consistency(f1, f2):
|
||||
# return false if it finds a fingerprint fully included in another
|
||||
# max message worth checking is 1800, as above that they usually come too infrequently and not
|
||||
# usable for fingerprinting
|
||||
|
||||
max_msg = 1800
|
||||
|
||||
is_f1_in_f2 = True
|
||||
for k in f1:
|
||||
if (k not in f2 or f1[k] != f2[k]) and k < max_msg:
|
||||
is_f1_in_f2 = False
|
||||
|
||||
is_f2_in_f1 = True
|
||||
for k in f2:
|
||||
if (k not in f1 or f2[k] != f1[k]) and k < max_msg:
|
||||
is_f2_in_f1 = False
|
||||
|
||||
return not is_f1_in_f2 and not is_f2_in_f1
|
||||
|
||||
|
||||
def check_can_ignition_conflicts(fingerprints, brands):
|
||||
# loops through all the fingerprints and exits if CAN ignition dedicated messages
|
||||
# are found in unexpected fingerprints
|
||||
|
||||
for brand_can, msgs_can in CAN_IGNITION_MSGS.items():
|
||||
for i, f in enumerate(fingerprints):
|
||||
for msg_can in msgs_can:
|
||||
if brand_can != brands[i] and msg_can[0] in f and msg_can[1] == f[msg_can[0]]:
|
||||
print("CAN ignition dedicated msg %d with len %d found in %s fingerprints!" % (msg_can[0], msg_can[1], brands[i]))
|
||||
print("TEST FAILED")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
fingerprints = _get_fingerprints()
|
||||
|
||||
fingerprints_flat: list[dict] = []
|
||||
car_names = []
|
||||
brand_names = []
|
||||
for brand in fingerprints:
|
||||
for car in fingerprints[brand]:
|
||||
fingerprints_flat += fingerprints[brand][car]
|
||||
for _ in range(len(fingerprints[brand][car])):
|
||||
car_names.append(car)
|
||||
brand_names.append(brand)
|
||||
|
||||
# first check if CAN ignition specific messages are unexpectedly included in other fingerprints
|
||||
check_can_ignition_conflicts(fingerprints_flat, brand_names)
|
||||
|
||||
valid = True
|
||||
for idx1, f1 in enumerate(fingerprints_flat):
|
||||
for idx2, f2 in enumerate(fingerprints_flat):
|
||||
if idx1 < idx2 and not check_fingerprint_consistency(f1, f2):
|
||||
valid = False
|
||||
print(f"Those two fingerprints are inconsistent {car_names[idx1]} {car_names[idx2]}")
|
||||
print("")
|
||||
print(', '.join("%d: %d" % v for v in sorted(f1.items())))
|
||||
print("")
|
||||
print(', '.join("%d: %d" % v for v in sorted(f2.items())))
|
||||
print("")
|
||||
|
||||
print(f"Found {len(fingerprints_flat)} individual fingerprints")
|
||||
if not valid or len(fingerprints_flat) == 0:
|
||||
print("TEST FAILED")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("TEST SUCCESSFUL")
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
import pytest
|
||||
import random
|
||||
import time
|
||||
|
|
|
@ -3,6 +3,7 @@ from collections import defaultdict
|
|||
import importlib
|
||||
from parameterized import parameterized_class
|
||||
import pytest
|
||||
import sys
|
||||
|
||||
from openpilot.common.realtime import DT_CTRL
|
||||
from openpilot.selfdrive.car.car_helpers import interfaces
|
||||
|
@ -20,8 +21,6 @@ MAX_LAT_JERK_UP_TOLERANCE = 0.5 # m/s^3
|
|||
# jerk is measured over half a second
|
||||
JERK_MEAS_T = 0.5
|
||||
|
||||
car_model_jerks: defaultdict[str, dict[str, float]] = defaultdict(dict)
|
||||
|
||||
|
||||
@parameterized_class('car_model', [(c,) for c in sorted(CAR_MODELS)])
|
||||
class TestLateralLimits:
|
||||
|
@ -44,7 +43,7 @@ class TestLateralLimits:
|
|||
|
||||
CarControllerParams = importlib.import_module(f'selfdrive.car.{CP.carName}.values').CarControllerParams
|
||||
cls.control_params = CarControllerParams(CP)
|
||||
cls.torque_params = get_torque_params(cls.car_model)
|
||||
cls.torque_params = get_torque_params()[cls.car_model]
|
||||
|
||||
@staticmethod
|
||||
def calculate_0_5s_jerk(control_params, torque_params):
|
||||
|
@ -64,9 +63,36 @@ class TestLateralLimits:
|
|||
|
||||
def test_jerk_limits(self):
|
||||
up_jerk, down_jerk = self.calculate_0_5s_jerk(self.control_params, self.torque_params)
|
||||
car_model_jerks[self.car_model] = {"up_jerk": up_jerk, "down_jerk": down_jerk}
|
||||
assert up_jerk <= MAX_LAT_JERK_UP + MAX_LAT_JERK_UP_TOLERANCE
|
||||
assert down_jerk <= MAX_LAT_JERK_DOWN
|
||||
|
||||
def test_max_lateral_accel(self):
|
||||
assert self.torque_params["MAX_LAT_ACCEL_MEASURED"] <= MAX_LAT_ACCEL
|
||||
|
||||
|
||||
class LatAccelReport:
|
||||
car_model_jerks: defaultdict[str, dict[str, float]] = defaultdict(dict)
|
||||
|
||||
def pytest_sessionfinish(self):
|
||||
print(f"\n\n---- Lateral limit report ({len(CAR_MODELS)} cars) ----\n")
|
||||
|
||||
max_car_model_len = max([len(car_model) for car_model in self.car_model_jerks])
|
||||
for car_model, _jerks in sorted(self.car_model_jerks.items(), key=lambda i: i[1]['up_jerk'], reverse=True):
|
||||
violation = _jerks["up_jerk"] > MAX_LAT_JERK_UP + MAX_LAT_JERK_UP_TOLERANCE or \
|
||||
_jerks["down_jerk"] > MAX_LAT_JERK_DOWN
|
||||
violation_str = " - VIOLATION" if violation else ""
|
||||
|
||||
print(f"{car_model:{max_car_model_len}} - up jerk: {round(_jerks['up_jerk'], 2):5} " +
|
||||
f"m/s^3, down jerk: {round(_jerks['down_jerk'], 2):5} m/s^3{violation_str}")
|
||||
|
||||
@pytest.fixture(scope="class", autouse=True)
|
||||
def class_setup(self, request):
|
||||
yield
|
||||
cls = request.cls
|
||||
if hasattr(cls, "control_params"):
|
||||
up_jerk, down_jerk = TestLateralLimits.calculate_0_5s_jerk(cls.control_params, cls.torque_params)
|
||||
self.car_model_jerks[cls.car_model] = {"up_jerk": up_jerk, "down_jerk": down_jerk}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(pytest.main([__file__, '-n0', '--no-summary'], plugins=[LatAccelReport()])) # noqa: TID251
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
import capnp
|
||||
import os
|
||||
import importlib
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from openpilot.selfdrive.car.values import PLATFORMS
|
||||
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
|||
"GMC_ACADIA" = [1.6, 1.6, 0.2]
|
||||
"LEXUS_IS_TSS2" = [2.0, 2.0, 0.1]
|
||||
"HYUNDAI_KONA_EV_2ND_GEN" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_IONIQ_6" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_IONIQ_6" = [2.5, 2.5, 0.005]
|
||||
"HYUNDAI_AZERA_6TH_GEN" = [1.8, 1.8, 0.1]
|
||||
"HYUNDAI_AZERA_HEV_6TH_GEN" = [1.8, 1.8, 0.1]
|
||||
"KIA_K8_HEV_1ST_GEN" = [2.5, 2.5, 0.1]
|
||||
|
|
|
@ -41,7 +41,7 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
|||
"HYUNDAI_TUCSON_4TH_GEN" = [2.960174, 2.860284, 0.108745]
|
||||
"JEEP_GRAND_CHEROKEE_2019" = [2.30972, 1.289689569171081, 0.117048]
|
||||
"JEEP_GRAND_CHEROKEE" = [2.27116, 1.4057367824262523, 0.11725947414922003]
|
||||
"KIA_EV6" = [3.2, 2.093457, 0.05]
|
||||
"KIA_EV6" = [3.2, 2.093457, 0.005]
|
||||
"KIA_K5_2021" = [2.405339728085138, 1.460032270828705, 0.11650989850813716]
|
||||
"KIA_NIRO_EV" = [2.9215954981365337, 2.1500583840260044, 0.09236802474810267]
|
||||
"KIA_SORENTO" = [2.464854685101844, 1.5335274218367956, 0.12056170567599558]
|
||||
|
|
|
@ -214,6 +214,7 @@ FW_VERSIONS = {
|
|||
b'8646F0601400 ',
|
||||
b'8646F0603400 ',
|
||||
b'8646F0603500 ',
|
||||
b'8646F0604000 ',
|
||||
b'8646F0604100 ',
|
||||
b'8646F0605000 ',
|
||||
b'8646F0606000 ',
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
from hypothesis import given, settings, strategies as st
|
||||
|
||||
from cereal import car
|
||||
|
|
|
@ -165,7 +165,7 @@ class CAR(Platforms):
|
|||
ToyotaCarDocs("Toyota Corolla Hatchback 2019-22", video_link="https://www.youtube.com/watch?v=_66pXk0CBYA"),
|
||||
# Hybrid platforms
|
||||
ToyotaCarDocs("Toyota Corolla Hybrid 2020-22"),
|
||||
ToyotaCarDocs("Toyota Corolla Hybrid (Non-US only) 2020-23", min_enable_speed=7.5),
|
||||
ToyotaCarDocs("Toyota Corolla Hybrid (South America only) 2020-23", min_enable_speed=7.5),
|
||||
ToyotaCarDocs("Toyota Corolla Cross Hybrid (Non-US only) 2020-22", min_enable_speed=7.5),
|
||||
ToyotaCarDocs("Lexus UX Hybrid 2019-23"),
|
||||
],
|
||||
|
|
|
@ -119,6 +119,7 @@ FW_VERSIONS = {
|
|||
b'\xf1\x8704L906056BP\xf1\x894729',
|
||||
b'\xf1\x8704L906056EK\xf1\x896391',
|
||||
b'\xf1\x8705L906023BC\xf1\x892688',
|
||||
b'\xf1\x8705L906023MH\xf1\x892588',
|
||||
],
|
||||
(Ecu.srs, 0x715, None): [
|
||||
b'\xf1\x873Q0959655AL\xf1\x890505\xf1\x82\x0e1411001413001203151311031100',
|
||||
|
@ -128,6 +129,7 @@ FW_VERSIONS = {
|
|||
(Ecu.eps, 0x712, None): [
|
||||
b'\xf1\x872N0909143D\x00\xf1\x897010\xf1\x82\x05183AZ306A2',
|
||||
b'\xf1\x872N0909143E \xf1\x897021\xf1\x82\x05163AZ306A2',
|
||||
b'\xf1\x872N0909143H \xf1\x897045\xf1\x82\x05263AZ309A2',
|
||||
b'\xf1\x872N0909144K \xf1\x897045\xf1\x82\x05233AZ810A2',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x757, None): [
|
||||
|
@ -589,6 +591,7 @@ FW_VERSIONS = {
|
|||
b'\xf1\x8783A907115Q \xf1\x890001',
|
||||
],
|
||||
(Ecu.transmission, 0x7e1, None): [
|
||||
b'\xf1\x8709G927158DS\xf1\x893699',
|
||||
b'\xf1\x8709G927158DT\xf1\x893698',
|
||||
b'\xf1\x8709G927158FM\xf1\x893757',
|
||||
b'\xf1\x8709G927158GC\xf1\x893821',
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
import random
|
||||
import re
|
||||
|
||||
|
|
|
@ -261,14 +261,14 @@ class CAR(Platforms):
|
|||
)
|
||||
VOLKSWAGEN_CRAFTER_MK2 = VolkswagenMQBPlatformConfig(
|
||||
[
|
||||
VWCarDocs("Volkswagen Crafter 2017-23", video_link="https://youtu.be/4100gLeabmo"),
|
||||
VWCarDocs("Volkswagen e-Crafter 2018-23", video_link="https://youtu.be/4100gLeabmo"),
|
||||
VWCarDocs("Volkswagen Grand California 2019-23", video_link="https://youtu.be/4100gLeabmo"),
|
||||
VWCarDocs("MAN TGE 2017-23", video_link="https://youtu.be/4100gLeabmo"),
|
||||
VWCarDocs("MAN eTGE 2020-23", video_link="https://youtu.be/4100gLeabmo"),
|
||||
VWCarDocs("Volkswagen Crafter 2017-24", video_link="https://youtu.be/4100gLeabmo"),
|
||||
VWCarDocs("Volkswagen e-Crafter 2018-24", video_link="https://youtu.be/4100gLeabmo"),
|
||||
VWCarDocs("Volkswagen Grand California 2019-24", video_link="https://youtu.be/4100gLeabmo"),
|
||||
VWCarDocs("MAN TGE 2017-24", video_link="https://youtu.be/4100gLeabmo"),
|
||||
VWCarDocs("MAN eTGE 2020-24", video_link="https://youtu.be/4100gLeabmo"),
|
||||
],
|
||||
VolkswagenCarSpecs(mass=2100, wheelbase=3.64, minSteerSpeed=50 * CV.KPH_TO_MS),
|
||||
chassis_codes={"SY", "SZ"},
|
||||
chassis_codes={"SY", "SZ", "UY", "UZ"},
|
||||
wmis={WMI.VOLKSWAGEN_COMMERCIAL, WMI.MAN},
|
||||
)
|
||||
VOLKSWAGEN_GOLF_MK7 = VolkswagenMQBPlatformConfig(
|
||||
|
|
|
@ -8,7 +8,7 @@ from typing import SupportsFloat
|
|||
import cereal.messaging as messaging
|
||||
|
||||
from cereal import car, log, custom
|
||||
from cereal.visionipc import VisionIpcClient, VisionStreamType
|
||||
from msgq.visionipc import VisionIpcClient, VisionStreamType
|
||||
|
||||
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
|
@ -323,7 +323,7 @@ class Controls:
|
|||
else:
|
||||
safety_mismatch = pandaState.safetyModel not in IGNORED_SAFETY_MODES
|
||||
|
||||
# safety mismatch allows some time for boardd to set the safety mode and publish it back from panda
|
||||
# safety mismatch allows some time for pandad to set the safety mode and publish it back from panda
|
||||
if (safety_mismatch and self.sm.frame*DT_CTRL > 10.) or pandaState.safetyRxChecksInvalid or self.mismatch_counter >= 200:
|
||||
self.events.add(EventName.controlsMismatch)
|
||||
|
||||
|
@ -366,19 +366,18 @@ class Controls:
|
|||
# generic catch-all. ideally, a more specific event should be added above instead
|
||||
has_disable_events = self.events.contains(ET.NO_ENTRY) and (self.events.contains(ET.SOFT_DISABLE) or self.events.contains(ET.IMMEDIATE_DISABLE))
|
||||
no_system_errors = (not has_disable_events) or (len(self.events) == num_events)
|
||||
if (not self.sm.all_checks() or CS.canRcvTimeout) and no_system_errors:
|
||||
if not self.sm.all_checks() and no_system_errors:
|
||||
if not self.sm.all_alive():
|
||||
self.events.add(EventName.commIssue)
|
||||
elif not self.sm.all_freq_ok():
|
||||
self.events.add(EventName.commIssueAvgFreq)
|
||||
else: # invalid or can_rcv_timeout.
|
||||
else:
|
||||
self.events.add(EventName.commIssue)
|
||||
|
||||
logs = {
|
||||
'invalid': [s for s, valid in self.sm.valid.items() if not valid],
|
||||
'not_alive': [s for s, alive in self.sm.alive.items() if not alive],
|
||||
'not_freq_ok': [s for s, freq_ok in self.sm.freq_ok.items() if not freq_ok],
|
||||
'can_rcv_timeout': CS.canRcvTimeout,
|
||||
}
|
||||
if logs != self.logged_comm_issue:
|
||||
cloudlog.event("commIssue", error=True, **logs)
|
||||
|
|
|
@ -51,7 +51,7 @@ class Events:
|
|||
def __init__(self):
|
||||
self.events: list[int] = []
|
||||
self.static_events: list[int] = []
|
||||
self.events_prev = dict.fromkeys(EVENTS.keys(), 0)
|
||||
self.event_counters = dict.fromkeys(EVENTS.keys(), 0)
|
||||
|
||||
@property
|
||||
def names(self) -> list[int]:
|
||||
|
@ -66,7 +66,7 @@ class Events:
|
|||
bisect.insort(self.events, event_name)
|
||||
|
||||
def clear(self) -> None:
|
||||
self.events_prev = {k: (v + 1 if k in self.events else 0) for k, v in self.events_prev.items()}
|
||||
self.event_counters = {k: (v + 1 if k in self.events else 0) for k, v in self.event_counters.items()}
|
||||
self.events = self.static_events.copy()
|
||||
|
||||
def contains(self, event_type: str) -> bool:
|
||||
|
@ -85,7 +85,7 @@ class Events:
|
|||
if not isinstance(alert, Alert):
|
||||
alert = alert(*callback_args)
|
||||
|
||||
if DT_CTRL * (self.events_prev[e] + 1) >= alert.creation_delay:
|
||||
if DT_CTRL * (self.event_counters[e] + 1) >= alert.creation_delay:
|
||||
alert.alert_type = f"{EVENT_NAME[e]}/{et}"
|
||||
alert.event_type = et
|
||||
ret.append(alert)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Import('env', 'envCython', 'arch', 'messaging_python', 'common_python', 'opendbc_python')
|
||||
Import('env', 'envCython', 'arch', 'msgq_python', 'common_python', 'opendbc_python')
|
||||
|
||||
gen = "c_generated_code"
|
||||
|
||||
|
@ -60,7 +60,7 @@ lenv.Clean(generated_files, Dir(gen))
|
|||
generated_lat = lenv.Command(generated_files,
|
||||
source_list,
|
||||
f"cd {Dir('.').abspath} && python3 lat_mpc.py")
|
||||
lenv.Depends(generated_lat, [messaging_python, common_python, opendbc_python])
|
||||
lenv.Depends(generated_lat, [msgq_python, common_python, opendbc_python])
|
||||
|
||||
lenv["CFLAGS"].append("-DACADOS_WITH_QPOASES")
|
||||
lenv["CXXFLAGS"].append("-DACADOS_WITH_QPOASES")
|
||||
|
|
|
@ -14,7 +14,7 @@ from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper
|
|||
import cereal.messaging as messaging
|
||||
from cereal import log
|
||||
|
||||
LaneChangeState = log.LateralPlan.LaneChangeState
|
||||
LaneChangeState = log.LaneChangeState
|
||||
|
||||
|
||||
PATH_COST = 1.0
|
||||
|
|
|
@ -5,6 +5,8 @@ from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N, apply_dead
|
|||
from openpilot.selfdrive.controls.lib.pid import PIDController
|
||||
from openpilot.selfdrive.modeld.constants import ModelConstants
|
||||
|
||||
CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N]
|
||||
|
||||
LongCtrlState = car.CarControl.Actuators.LongControlState
|
||||
|
||||
|
||||
|
@ -70,19 +72,19 @@ class LongControl:
|
|||
# Interp control trajectory
|
||||
speeds = long_plan.speeds
|
||||
if len(speeds) == CONTROL_N:
|
||||
v_target_now = interp(t_since_plan, ModelConstants.T_IDXS[:CONTROL_N], speeds)
|
||||
a_target_now = interp(t_since_plan, ModelConstants.T_IDXS[:CONTROL_N], long_plan.accels)
|
||||
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, ModelConstants.T_IDXS[:CONTROL_N], speeds)
|
||||
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, ModelConstants.T_IDXS[:CONTROL_N], speeds)
|
||||
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, ModelConstants.T_IDXS[:CONTROL_N], speeds)
|
||||
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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Import('env', 'envCython', 'arch', 'messaging_python', 'common_python', 'opendbc_python')
|
||||
Import('env', 'envCython', 'arch', 'msgq_python', 'common_python', 'opendbc_python')
|
||||
|
||||
gen = "c_generated_code"
|
||||
|
||||
|
@ -66,7 +66,7 @@ lenv.Clean(generated_files, Dir(gen))
|
|||
generated_long = lenv.Command(generated_files,
|
||||
source_list,
|
||||
f"cd {Dir('.').abspath} && python3 long_mpc.py")
|
||||
lenv.Depends(generated_long, [messaging_python, common_python, opendbc_python])
|
||||
lenv.Depends(generated_long, [msgq_python, common_python, opendbc_python])
|
||||
|
||||
lenv["CFLAGS"].append("-DACADOS_WITH_QPOASES")
|
||||
lenv["CXXFLAGS"].append("-DACADOS_WITH_QPOASES")
|
||||
|
|
|
@ -89,9 +89,9 @@ class LongitudinalPlanner:
|
|||
|
||||
@staticmethod
|
||||
def parse_model(model_msg, model_error):
|
||||
if (len(model_msg.position.x) == 33 and
|
||||
len(model_msg.velocity.x) == 33 and
|
||||
len(model_msg.acceleration.x) == 33):
|
||||
if (len(model_msg.position.x) == ModelConstants.IDX_N and
|
||||
len(model_msg.velocity.x) == ModelConstants.IDX_N and
|
||||
len(model_msg.acceleration.x) == ModelConstants.IDX_N):
|
||||
x = np.interp(T_IDXS_MPC, ModelConstants.T_IDXS, model_msg.position.x) - model_error * T_IDXS_MPC
|
||||
v = np.interp(T_IDXS_MPC, ModelConstants.T_IDXS, model_msg.velocity.x) - model_error
|
||||
a = np.interp(T_IDXS_MPC, ModelConstants.T_IDXS, model_msg.acceleration.x)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
import random
|
||||
|
||||
from openpilot.selfdrive.controls.lib.events import Alert, EVENTS
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
from parameterized import parameterized
|
||||
|
||||
from cereal import car, log
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
import pytest
|
||||
import math
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
import pytest
|
||||
import itertools
|
||||
import numpy as np
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
import pytest
|
||||
import itertools
|
||||
from parameterized import parameterized_class
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
import cereal.messaging as messaging
|
||||
|
||||
from openpilot.selfdrive.test.process_replay import replay_process_with_name
|
||||
|
|
|
@ -4,7 +4,7 @@ from parameterized import parameterized
|
|||
from cereal import log, car
|
||||
import cereal.messaging as messaging
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.selfdrive.boardd.boardd_api_impl import can_list_to_can_capnp
|
||||
from openpilot.selfdrive.pandad.pandad_api_impl import can_list_to_can_capnp
|
||||
from openpilot.selfdrive.car.fingerprints import _FINGERPRINTS
|
||||
from openpilot.selfdrive.car.toyota.values import CAR as TOYOTA
|
||||
from openpilot.selfdrive.car.mazda.values import CAR as MAZDA
|
||||
|
@ -105,7 +105,7 @@ def test_startup_alert(expected_event, car_model, fw_versions, brand):
|
|||
|
||||
msgs = [[addr, 0, b'\x00'*length, 0] for addr, length in finger.items()]
|
||||
for _ in range(1000):
|
||||
# card waits for boardd to echo back that it has changed the multiplexing mode
|
||||
# card waits for pandad to echo back that it has changed the multiplexing mode
|
||||
if not params.get_bool("ObdMultiplexingChanged"):
|
||||
params.put_bool("ObdMultiplexingChanged", True)
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue