diff --git a/.coveragerc-app b/.coveragerc-app
deleted file mode 100644
index 18c81e3b48..0000000000
--- a/.coveragerc-app
+++ /dev/null
@@ -1,3 +0,0 @@
-[run]
-concurrency=multiprocessing
-
diff --git a/.editorconfig b/.editorconfig
index e0da061025..879e6eebca 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,7 +5,7 @@ end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
-[{*.py, *.pyx, *pxd}]
+[{*.py, *.pyx, *.pxd}]
charset = utf-8
indent_style = space
indent_size = 2
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 47b8af1905..a16eacbc69 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -1,26 +1,31 @@
---
name: Bug report
-about: Create a report to help us improve openpilot
+about: For issues with running openpilot on your comma device
title: ''
-labels: ''
+labels: 'bug'
assignees: ''
-
---
**Describe the bug**
-A clear and concise description of what the bug is.
+
+
**How to reproduce or log data**
-Steps to reproduce the behavior, or a explorer/cabana link to the exact drive and timestamp of when the bug occurred.
+
+
**Expected behavior**
-A clear and concise description of what you expected to happen.
+
+
**Device/Version information (please complete the following information):**
- - Device: [e.g. EON/EON Gold]
- - Dongle ID: [e.g. 77611a1fac303767, can be found in Settings -> Device -> Dongle ID]
- - Version: [e.g. 0.6.4], or commit hash when on devel
- - Car make/model [e.g. Toyota Prius 2016]
+ - Device: [e.g. EON/EON Gold/comma two]
+ - Dongle ID: [e.g. 77611a1fac303767, can be found in Settings -> Device -> Dongle ID or my.comma.ai/useradmin]
+ - Route: [e.g. 77611a1fac303767|2020-05-11--16-37-07, can be found in my.comma.ai/useradmin]
+ - Timestamp: [When in the route the bug occurs (e.g. 4min 30s into the drive)]
+ - Version: [commit hash when on a non-release branch, or version number when on devel or release2 (e.g. 0.7.6)]
+ - Car make/model: [e.g. Toyota Prius 2016]
**Additional context**
-Add any other context about the problem here.
+
+
diff --git a/.github/ISSUE_TEMPLATE/bug_report_pc.md b/.github/ISSUE_TEMPLATE/bug_report_pc.md
new file mode 100644
index 0000000000..c1471ec61c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report_pc.md
@@ -0,0 +1,25 @@
+---
+name: PC Bug report
+about: For issues with running openpilot on PC
+title: ''
+labels: 'PC'
+assignees: ''
+---
+
+**Describe the bug**
+
+
+
+**How to reproduce or log data**
+
+
+
+**Expected behavior**
+
+
+
+**Additional context**
+
+
+
+Operating system: [e.g. Ubuntu 16.04]
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000..fcb4dcd2a6
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,8 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Community Wiki
+ url: https://github.com/commaai/openpilot/wiki
+ about: Check out our community wiki
+ - name: Community Discord
+ urli: https://discord.comma.ai
+ about: Check out our community discord
diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md
new file mode 100644
index 0000000000..96a6047703
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/enhancement.md
@@ -0,0 +1,8 @@
+---
+name: Enhancement
+about: For suggestions for openpilot enhancements
+title: ''
+labels: 'enhancement'
+assignees: ''
+---
+
diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md
new file mode 100644
index 0000000000..2cd62791f9
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/question.md
@@ -0,0 +1,17 @@
+---
+name: Question
+about: For questions about openpilot
+title: ''
+labels: 'question'
+assignees: ''
+---
+
+
diff --git a/.github/PULL_REQUEST_TEMPLATE/bugfix.md b/.github/PULL_REQUEST_TEMPLATE/bugfix.md
new file mode 100644
index 0000000000..e28661db3b
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/bugfix.md
@@ -0,0 +1,15 @@
+---
+name: Bug fix
+about: For openpilot bug fixes
+title: ''
+labels: 'bugfix'
+assignees: ''
+---
+
+**Description**
+
+
+
+**Verification**
+
+
diff --git a/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md b/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md
new file mode 100644
index 0000000000..d0c8bc58e4
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md
@@ -0,0 +1,19 @@
+---
+name: Car Bug fix
+about: For vehicle/brand specifc bug fixes
+title: ''
+labels: 'car bug fix'
+assignees: ''
+---
+
+**Description**
+
+
+
+**Verification**
+
+
+
+**Route**
+
+Route: [a route with the bug fix]
diff --git a/.github/PULL_REQUEST_TEMPLATE/car_port.md b/.github/PULL_REQUEST_TEMPLATE/car_port.md
new file mode 100644
index 0000000000..b81c293885
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/car_port.md
@@ -0,0 +1,14 @@
+---
+name: Car port
+about: For new car ports
+title: ''
+labels: 'car port'
+assignees: ''
+---
+
+**Checklist**
+
+- [ ] added to README
+- [ ] test route added to [test_car_models](../../selfdrive/test/test_car_models.py)
+- [ ] route with openpilot:
+- [ ] route with stock system:
diff --git a/.github/PULL_REQUEST_TEMPLATE/fingerprint.md b/.github/PULL_REQUEST_TEMPLATE/fingerprint.md
new file mode 100644
index 0000000000..466d4f98f4
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/fingerprint.md
@@ -0,0 +1,11 @@
+---
+name: Fingerprint
+about: For adding fingerprints to existing cars
+title: ''
+labels: 'fingerprint'
+assignees: ''
+---
+
+Discord username: []
+
+Route: []
diff --git a/.github/PULL_REQUEST_TEMPLATE/refactor.md b/.github/PULL_REQUEST_TEMPLATE/refactor.md
new file mode 100644
index 0000000000..1ee21c1bba
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/refactor.md
@@ -0,0 +1,15 @@
+---
+name: Refactor
+about: For code refactors
+title: ''
+labels: 'refactor'
+assignees: ''
+---
+
+**Description**
+
+
+
+**Verification**
+
+
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000000..def16ca23e
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,8 @@
+version: 2
+updates:
+- package-ecosystem: pip
+ directory: "/"
+ schedule:
+ interval: daily
+ time: '15:00'
+ open-pull-requests-limit: 10
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000000..d09fb55490
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index e8f4ad5511..7d0ae1f456 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -1,37 +1,25 @@
-name: Openpilot Tests
-on: [push, pull_request]
+name: openpilot tests
+on:
+ push:
+ pull_request:
+ schedule:
+ - cron: '0 * * * *'
env:
RUN: docker run --shm-size 1G --rm tmppilot /bin/sh -c
PERSIST: docker run --shm-size 1G --name tmppilot tmppilot /bin/sh -c
- LOAD: docker load -i tmppilot.tar.gz/tmppilot.tar.gz
CI_RUN: docker run -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID --rm tmppilotci /bin/bash -c
UNIT_TEST: coverage run --append -m unittest discover
+ BUILD: |
+ docker pull $(grep -ioP '(?<=^from)\s+\S+' Dockerfile.openpilot) || true
+ docker pull docker.io/commaai/openpilotci:latest || true
+ docker build --cache-from docker.io/commaai/openpilotci:latest -t tmppilot -f Dockerfile.openpilot .
jobs:
- build:
- name: build
- runs-on: ubuntu-16.04
- steps:
- - uses: actions/checkout@v2
- with:
- submodules: true
- - name: Build docker image
- run: |
- docker pull $(grep -ioP '(?<=^from)\s+\S+' Dockerfile.openpilot) || true
- docker pull docker.io/commaai/openpilot:latest || true
-
- docker build --cache-from docker.io/commaai/openpilot:latest -t tmppilot -f Dockerfile.openpilot .
- docker save tmppilot:latest | gzip > tmppilot.tar.gz
- - uses: actions/upload-artifact@v2
- with:
- name: tmppilot.tar.gz
- path: tmppilot.tar.gz
-
build_release:
name: build release
runs-on: ubuntu-16.04
- timeout-minutes: 30
+ timeout-minutes: 50
env:
TEST_DIR: tmppilot
steps:
@@ -44,111 +32,151 @@ jobs:
cp -pR --parents $(cat release/files_common) $TEST_DIR
cp Dockerfile.openpilot $TEST_DIR
- # copy submodules
- cp -pR panda/ opendbc/ cereal/ $TEST_DIR
-
# need this to build on x86
cp -pR --parents phonelibs/libyuv phonelibs/snpe \
external/bin selfdrive/modeld/runners $TEST_DIR
# need these so docker copy won't fail
- cp Pipfile Pipfile.lock flake8_openpilot.sh pylint_openpilot.sh .pylintrc \
- .coveragerc-app $TEST_DIR
+ cp Pipfile Pipfile.lock .pylintrc .pre-commit-config.yaml $TEST_DIR
cd $TEST_DIR
- mkdir pyextra laika laika_repo tools release
- - name: Build
+ mkdir laika laika_repo tools
+ - name: Build Docker image
+ run: cd $TEST_DIR && eval "$BUILD"
+ - name: Build openpilot and run quick check
run: |
- cd $TEST_DIR
- docker pull $(grep -ioP '(?<=^from)\s+\S+' Dockerfile.openpilot) || true
- docker pull docker.io/commaai/openpilot:latest || true
- docker build --cache-from docker.io/commaai/openpilot:latest -t tmppilot -f Dockerfile.openpilot .
+ $RUN "cd /tmp/openpilot && \
+ scons -j$(nproc) && \
+ $UNIT_TEST selfdrive/car"
- push:
- name: push
+ build_mac:
+ name: build macos
+ runs-on: macos-10.15
+ timeout-minutes: 35
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: true
+ - name: Cache dependencies
+ id: dependency-cache
+ uses: actions/cache@v2
+ with:
+ path: |
+ ~/.pyenv
+ ~/Library/Caches/pip
+ ~/Library/Caches/pipenv
+ ~/Library/Caches/Homebrew
+ key: ${{ hashFiles('tools/mac_setup.sh') }}
+ - name: Install dependencies
+ run: ./tools/mac_setup.sh
+ - name: Build openpilot
+ run: eval "$(pyenv init -)" && scons -j$(nproc)
+ - name: Brew cleanup
+ run: brew cleanup # keeps our cache small
+
+ docker_push:
+ name: docker push
runs-on: ubuntu-16.04
- needs: build
+ timeout-minutes: 50
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot'
+ needs: static_analysis # hack to ensure slow tests run first since this and static_analysis are fast
steps:
- - uses: actions/download-artifact@v1
+ - uses: actions/checkout@v2
with:
- name: tmppilot.tar.gz
- - name: Load image
- run: $LOAD
- - name: Login to dockerhub
- run: docker login -u wmelching -p ${{ secrets.DOCKERHUB_TOKEN }}
- - name: Tag image
- run: docker tag tmppilot docker.io/commaai/openpilot:latest
- - name: Push image
- run: docker push docker.io/commaai/openpilot:latest
+ submodules: true
+ - name: Build Docker image
+ run: eval "$BUILD"
+ - name: Push to dockerhub
+ run: |
+ docker login -u wmelching -p ${{ secrets.COMMA_DOCKERHUB_TOKEN}}
+ docker tag tmppilot docker.io/commaai/openpilotci:latest
+ docker push docker.io/commaai/openpilotci:latest
- linter:
- name: linter
+ docker_push_prebuilt:
+ name: docker push prebuilt
runs-on: ubuntu-16.04
- needs: build
+ timeout-minutes: 50
+ if: github.event_name == 'schedule' && github.repository == 'commaai/openpilot'
+ needs: [static_analysis, unit_tests, process_replay, test_longitudinal, test_car_models]
steps:
- - uses: actions/download-artifact@v1
+ - uses: actions/checkout@v2
with:
- name: tmppilot.tar.gz
- - name: Load image
- run: $LOAD
- - name: flake8
- run: $RUN "cd /tmp/openpilot/ && ./flake8_openpilot.sh"
- - name: pylint
- run: $RUN "cd /tmp/openpilot/ && ./pylint_openpilot.sh"
+ submodules: true
+ - name: Build Docker image
+ run: echo "RUN cd /tmp/openpilot && scons -c && scons -j3" >> Dockerfile.openpilot && eval "$BUILD"
+ - name: Push to dockerhub
+ run: |
+ docker login -u wmelching -p ${{ secrets.COMMA_DOCKERHUB_TOKEN}}
+ docker tag tmppilot docker.io/commaai/openpilot:latest
+ docker push docker.io/commaai/openpilot:latest
+
+ static_analysis:
+ name: static analysis
+ runs-on: ubuntu-16.04
+ timeout-minutes: 50
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: true
+ - name: Build Docker image
+ run: eval "$BUILD"
+ - name: pre-commit
+ run: $RUN "cd /tmp/openpilot/ && git init && git add -A && pre-commit run --all"
unit_tests:
name: unit tests
runs-on: ubuntu-16.04
- needs: build
+ timeout-minutes: 50
steps:
- - uses: actions/download-artifact@v1
+ - uses: actions/checkout@v2
with:
- name: tmppilot.tar.gz
- - name: Load image
- run: $LOAD
+ submodules: true
+ - name: Build Docker image
+ run: eval "$BUILD"
- name: Run unit tests
run: |
$PERSIST "cd /tmp/openpilot && \
+ scons -j$(nproc) && \
coverage run selfdrive/test/test_fingerprints.py && \
$UNIT_TEST common && \
$UNIT_TEST opendbc/can && \
$UNIT_TEST selfdrive/boardd && \
$UNIT_TEST selfdrive/controls && \
+ $UNIT_TEST selfdrive/monitoring && \
$UNIT_TEST selfdrive/loggerd && \
$UNIT_TEST selfdrive/car && \
$UNIT_TEST selfdrive/locationd && \
$UNIT_TEST selfdrive/athena && \
+ $UNIT_TEST selfdrive/thermald && \
$UNIT_TEST tools/lib/tests"
- name: Upload coverage to Codecov
run: |
docker commit tmppilot tmppilotci
- $CI_RUN "cd /tmp/openpilot && bash <(curl -s https://codecov.io/bash) -Z -F unit_tests"
+ $CI_RUN "cd /tmp/openpilot && bash <(curl -s https://codecov.io/bash) -v -F unit_tests"
process_replay:
name: process replay
runs-on: ubuntu-16.04
- needs: build
- timeout-minutes: 30
+ timeout-minutes: 50
steps:
- - uses: actions/download-artifact@v1
+ - uses: actions/checkout@v2
with:
- name: tmppilot.tar.gz
- - name: Load image
- run: $LOAD
+ submodules: true
+ - name: Build Docker image
+ run: eval "$BUILD"
- name: Run replay
run: |
- $PERSIST "cd /tmp/openpilot && CI=1 coverage run selfdrive/test/process_replay/test_processes.py"
+ $PERSIST "cd /tmp/openpilot && \
+ scons -j$(nproc) && \
+ CI=1 coverage run selfdrive/test/process_replay/test_processes.py"
- name: Upload coverage to Codecov
run: |
docker commit tmppilot tmppilotci
- $CI_RUN "cd /tmp/openpilot && bash <(curl -s https://codecov.io/bash) -Z -F process_replay"
- - name: Copy diff
+ $CI_RUN "cd /tmp/openpilot && bash <(curl -s https://codecov.io/bash) -v -F process_replay"
+ - name: Print diff
if: always()
run: |
docker cp tmppilot:/tmp/openpilot/selfdrive/test/process_replay/diff.txt diff.txt
- - name: Print diff
- if: always()
- run: cat diff.txt
+ cat diff.txt
- uses: actions/upload-artifact@v2
if: always()
with:
@@ -158,17 +186,20 @@ jobs:
test_longitudinal:
name: longitudinal
runs-on: ubuntu-16.04
- needs: build
- timeout-minutes: 30
+ timeout-minutes: 50
steps:
- - uses: actions/download-artifact@v1
+ - uses: actions/checkout@v2
with:
- name: tmppilot.tar.gz
- - name: Load image
- run: $LOAD
+ submodules: true
+ - name: Build Docker image
+ run: eval "$BUILD"
- name: Test longitudinal
run: |
- $PERSIST "cd /tmp/openpilot/selfdrive/test/longitudinal_maneuvers && OPTEST=1 ./test_longitudinal.py"
+ $PERSIST "mkdir -p /tmp/openpilot/selfdrive/test/out && \
+ cd /tmp/openpilot/ && \
+ scons -j$(nproc) && \
+ cd selfdrive/test/longitudinal_maneuvers && \
+ OPTEST=1 ./test_longitudinal.py"
- name: Copy artifacts
if: always()
run: |
@@ -183,18 +214,21 @@ jobs:
test_car_models:
name: test car models
runs-on: ubuntu-16.04
- needs: build
- timeout-minutes: 30
+ timeout-minutes: 50
steps:
- - uses: actions/download-artifact@v1
+ - uses: actions/checkout@v2
with:
- name: tmppilot.tar.gz
- - name: Load image
- run: $LOAD
+ submodules: true
+ - name: Build Docker image
+ run: eval "$BUILD"
- name: Test car models
run: |
- $PERSIST "mkdir -p /data/params && cd /tmp/openpilot && coverage run --parallel-mode --concurrency=multiprocessing --rcfile=./.coveragerc-app selfdrive/test/test_car_models.py && coverage combine"
+ $PERSIST "cd /tmp/openpilot && \
+ scons -j$(nproc) && \
+ coverage run --parallel-mode -m nose --processes=4 --process-timeout=60 \
+ selfdrive/test/test_models.py && \
+ coverage combine"
- name: Upload coverage to Codecov
run: |
docker commit tmppilot tmppilotci
- $CI_RUN "cd /tmp/openpilot && bash <(curl -s https://codecov.io/bash) -Z -F test_car_models"
+ $CI_RUN "cd /tmp/openpilot && bash <(curl -s https://codecov.io/bash) -v -F test_car_models"
diff --git a/.github/workflows/update-pipfile.yml b/.github/workflows/update-pipfile.yml
new file mode 100644
index 0000000000..15bab0ec38
--- /dev/null
+++ b/.github/workflows/update-pipfile.yml
@@ -0,0 +1,23 @@
+name: "Update Pipfile.lock"
+on:
+ schedule:
+ - cron: '00 15 * * 1' # Every monday on 15:00 UTC
+
+jobs:
+ piplock:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ - run: pip install wheel
+ - run: pip install pipenv
+ - run: pipenv lock
+ - uses: actions/upload-artifact@v2
+ with:
+ name: "Pipfile lock"
+ path: Pipfile.lock
+ - uses: peter-evans/create-pull-request@v2
+ with:
+ title: "Update Pipfile.lock (dependencies)"
+ branch: update-pipfile
+ commit-message: "[Bot] Update Pipfile.lock dependencies"
diff --git a/.gitignore b/.gitignore
index c6efe5cf35..b8d9a39b4a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,9 +54,15 @@ openpilot
notebooks
xx
panda_jungle
+apks
+openpilot-apks
.coverage*
coverage.xml
htmlcov
pandaextra
+.mypy_cache/
+flycheck_*
+
+cppcheck_report.txt
diff --git a/.gitmodules b/.gitmodules
index 3d228f5cd3..1e6110b7a6 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,13 +7,9 @@
[submodule "laika_repo"]
path = laika_repo
url = ../../commaai/laika.git
-[submodule "apks"]
- path = apks
- url = ../../commaai/openpilot-apks.git
[submodule "cereal"]
path = cereal
url = ../../commaai/cereal.git
-
[submodule "rednose_repo"]
path = rednose_repo
url = ../../commaai/rednose.git
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000000..1cd805de4a
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,47 @@
+repos:
+- repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: master
+ hooks:
+ - id: check-ast
+ - id: check-json
+ - id: check-xml
+ - id: check-yaml
+ - id: check-merge-conflict
+ - id: check-symlinks
+- repo: https://github.com/pre-commit/mirrors-mypy
+ rev: master
+ hooks:
+ - id: mypy
+ exclude: '^(pyextra)|(external)|(cereal)|(rednose)|(panda)|(laika)|(opendbc)|(laika_repo)|(rednose_repo)/'
+ additional_dependencies: ['git+https://github.com/numpy/numpy-stubs']
+- repo: https://github.com/PyCQA/flake8
+ rev: master
+ hooks:
+ - id: flake8
+ exclude: '^(pyextra)|(external)|(cereal)|(rednose)|(panda)|(laika)|(opendbc)|(laika_repo)|(rednose_repo)|(selfdrive/debug)/'
+ args:
+ - --select=F,E112,E113,E304,E501,E502,E701,E702,E703,E71,E72,E731,W191,W6
+ - --max-line-length=240
+ - --statistics
+- repo: local
+ hooks:
+ - id: pylint
+ name: pylint
+ entry: pylint
+ language: system
+ types: [python]
+ exclude: '^(pyextra)|(external)|(cereal)|(rednose)|(panda)|(laika)|(laika_repo)|(rednose_repo)/'
+- repo: local
+ hooks:
+ - id: cppcheck
+ name: cppcheck
+ entry: cppcheck
+ language: system
+ types: [c++]
+ exclude: '^(phonelibs)|(external)|(cereal)|(opendbc)|(panda)|(tools)|(selfdrive/modeld/thneed/debug)|(selfdrive/modeld/test)|(selfdrive/camerad/test)/|(installer)'
+ args:
+ - --error-exitcode=1
+ - --language=c++
+ - --quiet
+ - --force
+ - -j8
diff --git a/.pylintrc b/.pylintrc
index 64a55daf8f..be7701c906 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -3,7 +3,7 @@
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code
-extension-pkg-whitelist=scipy
+extension-pkg-whitelist=scipy cereal.messaging.messaging_pyx
# Add files or directories to the blacklist. They should be base names, not
# paths.
@@ -54,121 +54,7 @@ confidence=
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
-disable=print-statement,
- parameter-unpacking,
- unpacking-in-except,
- old-raise-syntax,
- backtick,
- long-suffix,
- old-ne-operator,
- old-octal-literal,
- import-star-module-level,
- non-ascii-bytes-literal,
- raw-checker-failed,
- bad-inline-option,
- locally-disabled,
- locally-enabled,
- file-ignored,
- suppressed-message,
- useless-suppression,
- deprecated-pragma,
- apply-builtin,
- basestring-builtin,
- buffer-builtin,
- cmp-builtin,
- coerce-builtin,
- execfile-builtin,
- file-builtin,
- long-builtin,
- raw_input-builtin,
- reduce-builtin,
- standarderror-builtin,
- unicode-builtin,
- xrange-builtin,
- coerce-method,
- delslice-method,
- getslice-method,
- setslice-method,
- no-absolute-import,
- old-division,
- dict-iter-method,
- dict-view-method,
- next-method-called,
- metaclass-assignment,
- indexing-exception,
- raising-string,
- reload-builtin,
- oct-method,
- hex-method,
- nonzero-method,
- cmp-method,
- input-builtin,
- round-builtin,
- intern-builtin,
- unichr-builtin,
- map-builtin-not-iterating,
- zip-builtin-not-iterating,
- range-builtin-not-iterating,
- filter-builtin-not-iterating,
- using-cmp-argument,
- eq-without-hash,
- div-method,
- idiv-method,
- rdiv-method,
- exception-message-attribute,
- invalid-str-codec,
- sys-max-int,
- bad-python3-import,
- deprecated-string-function,
- deprecated-str-translate-call,
- deprecated-itertools-function,
- deprecated-types-field,
- next-method-defined,
- dict-items-not-iterating,
- dict-keys-not-iterating,
- dict-values-not-iterating,
- bad-indentation,
- line-too-long,
- missing-docstring,
- multiple-statements,
- bad-continuation,
- invalid-name,
- too-many-arguments,
- too-many-locals,
- superfluous-parens,
- bad-whitespace,
- too-many-instance-attributes,
- wrong-import-position,
- ungrouped-imports,
- wrong-import-order,
- protected-access,
- trailing-whitespace,
- too-many-branches,
- too-few-public-methods,
- too-many-statements,
- trailing-newlines,
- attribute-defined-outside-init,
- too-many-return-statements,
- too-many-public-methods,
- unused-argument,
- old-style-class,
- no-init,
- len-as-condition,
- unneeded-not,
- no-self-use,
- multiple-imports,
- no-else-return,
- logging-not-lazy,
- fixme,
- redefined-outer-name,
- unused-variable,
- unsubscriptable-object,
- expression-not-assigned,
- too-many-boolean-expressions,
- consider-using-ternary,
- invalid-unary-operand-type,
- relative-import,
- deprecated-lambda
+disable=C,R,W0613,W0511,W0212,W0201,W0311,W0106,W0603,W0621,W0703,E1136
# Enable the message, report, category or checker with the given id(s). You can
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index dc42a314a5..b8564c1e85 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,7 +2,7 @@
Our software is open source so you can solve your own problems without needing help from others. And if you solve a problem and are so kind, you can upstream it for the rest of the world to use.
-Most open source development activity is coordinated through our [Discord](https://discord.comma.ai). A lot of documentation is available on our [medium](https://medium.com/@comma_ai/)
+Most open source development activity is coordinated through our [Discord](https://discord.comma.ai). A lot of documentation is available on our [medium](https://medium.com/@comma_ai/).
## Getting Started
@@ -18,11 +18,11 @@ You can test your changes on your machine by running `run_docker_tests.sh`. This
### Automated Testing
-All PRs are automatically checked by Github Actions. Check out `.github/workflows/` for what Github Actions runs. Any new tests sould be added to Github Actions.
+All PRs and commits are automatically checked by Github Actions. Check out `.github/workflows/` for what Github Actions runs. Any new tests sould be added to Github Actions.
### Code Style and Linting
-Code is automatically checked for style by Github Actions as part of the automated tests. You can also run these tests yourself by running `pylint_openpilot.sh` and `flake8_openpilot.sh`.
+Code is automatically checked for style by Github Actions as part of the automated tests. You can also run these tests yourself by running `pre-commit run --all`.
## Car Ports (openpilot)
@@ -48,3 +48,4 @@ Modules that are in seperate repositories include:
* laika
* opendbc
* panda
+* rednose
diff --git a/Dockerfile.openpilot b/Dockerfile.openpilot
index a9f58f752c..8577282126 100644
--- a/Dockerfile.openpilot
+++ b/Dockerfile.openpilot
@@ -1,7 +1,8 @@
FROM ubuntu:16.04
ENV PYTHONUNBUFFERED 1
+ENV PYTHONPATH /tmp/openpilot:${PYTHONPATH}
-RUN apt-get update && apt-get install -y \
+RUN apt-get update && apt-get install -y --no-install-recommends \
autoconf \
build-essential \
bzip2 \
@@ -9,9 +10,11 @@ RUN apt-get update && apt-get install -y \
libcapnp-dev \
clang \
cmake \
+ cppcheck \
curl \
ffmpeg \
git \
+ iputils-ping \
libarchive-dev \
libbz2-dev \
libcurl4-openssl-dev \
@@ -22,12 +25,10 @@ RUN apt-get update && apt-get install -y \
libglfw3-dev \
libglib2.0-0 \
liblzma-dev \
- libmysqlclient-dev \
libomp-dev \
libopencv-dev \
libssl-dev \
libsqlite3-dev \
- libtool \
libusb-1.0-0-dev \
libczmq-dev \
libzmq3-dev \
@@ -37,11 +38,10 @@ RUN apt-get update && apt-get install -y \
opencl-headers \
python-dev \
python-pip \
- screen \
+ qt5-default \
sudo \
- vim \
- wget
-
+ wget \
+ && rm -rf /var/lib/apt/lists/*
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
ENV LANG en_US.UTF-8
@@ -49,49 +49,51 @@ ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash
-
ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}"
-RUN pyenv install 3.8.2
-RUN pyenv global 3.8.2
-RUN pyenv rehash
-
-RUN pip install pipenv==2018.11.26
-COPY Pipfile /tmp/
-COPY Pipfile.lock /tmp/
-
-RUN python --version
-RUN cd /tmp && pipenv install --system --deploy
-
-# Install subset of dev dependencies needed for CI
-RUN pip install matplotlib==3.1.1 dictdiffer==0.8.0 fastcluster==1.1.25 aenum==2.2.1 lru-dict==1.1.6 scipy==1.4.1 tenacity==5.1.1 azure-common==1.1.23 azure-nspkg==3.0.2 azure-storage-blob==2.1.0 azure-storage-common==2.1.0 azure-storage-nspkg==3.1.0 pycurl==7.43.0.3 coverage==5.1
-
-ENV PATH="/tmp/openpilot/external/bin:${PATH}"
-ENV PYTHONPATH /tmp/openpilot:${PYTHONPATH}
+COPY Pipfile Pipfile.lock /tmp/
+RUN pyenv install 3.8.2 && \
+ pyenv global 3.8.2 && \
+ pyenv rehash && \
+ pip install --no-cache-dir --upgrade pip==20.1.1 && \
+ pip install --no-cache-dir pipenv==2018.11.26 && \
+ cd /tmp && \
+ pipenv install --system --deploy --clear && \
+ pip uninstall -y pipenv && \
+ pip install --no-cache-dir \
+ matplotlib==3.1.1 \
+ dictdiffer==0.8.0 \
+ fastcluster==1.1.25 \
+ aenum==2.2.1 \
+ lru-dict==1.1.6 \
+ scipy==1.4.1 \
+ tenacity==5.1.1 \
+ azure-common==1.1.23 \
+ azure-nspkg==3.0.2 \
+ azure-storage-blob==2.1.0 \
+ azure-storage-common==2.1.0 \
+ azure-storage-nspkg==3.1.0 \
+ pycurl==7.43.0.3 \
+ coverage==5.1 \
+ pre-commit==2.4.0 \
+ parameterized==0.7.4
RUN mkdir -p /tmp/openpilot
-COPY ./flake8_openpilot.sh /tmp/openpilot/
-COPY ./pylint_openpilot.sh /tmp/openpilot/
-COPY ./.pylintrc /tmp/openpilot/
-
-COPY ./.coveragerc-app /tmp/openpilot/
+COPY SConstruct \
+ .pylintrc \
+ .pre-commit-config.yaml \
+ /tmp/openpilot/
COPY ./pyextra /tmp/openpilot/pyextra
COPY ./phonelibs /tmp/openpilot/phonelibs
-COPY ./external /tmp/openpilot/external
COPY ./laika /tmp/openpilot/laika
COPY ./laika_repo /tmp/openpilot/laika_repo
+COPY ./rednose /tmp/openpilot/rednose
COPY ./tools /tmp/openpilot/tools
COPY ./release /tmp/openpilot/release
COPY ./common /tmp/openpilot/common
COPY ./opendbc /tmp/openpilot/opendbc
COPY ./cereal /tmp/openpilot/cereal
COPY ./panda /tmp/openpilot/panda
-COPY ./rednose /tmp/openpilot/rednose
COPY ./selfdrive /tmp/openpilot/selfdrive
-
-COPY SConstruct /tmp/openpilot/SConstruct
-
-RUN mkdir -p /tmp/openpilot/selfdrive/test/out
-RUN cd /tmp/openpilot && scons -j$(nproc)
diff --git a/Jenkinsfile b/Jenkinsfile
index d34cd70375..dd0e2c12fa 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,25 +1,147 @@
-pipeline {
- agent {
- docker {
- image 'python:3.7.3'
- args '--user=root'
- }
+def phone(String ip, String step_label, String cmd) {
+ def ci_env = "CI=1 TEST_DIR=${env.TEST_DIR} GIT_BRANCH=${env.GIT_BRANCH} GIT_COMMIT=${env.GIT_COMMIT}"
+
+ withCredentials([file(credentialsId: 'id_rsa_public', variable: 'key_file')]) {
+ sh label: step_label,
+ script: """
+ ssh -tt -o StrictHostKeyChecking=no -i ${key_file} -p 8022 root@${ip} '${ci_env} /usr/bin/bash -le' <<'EOF'
+echo \$\$ > /dev/cpuset/app/tasks || true
+echo \$PPID > /dev/cpuset/app/tasks || true
+mkdir -p /dev/shm
+chmod 777 /dev/shm
+cd ${env.TEST_DIR} || true
+${cmd}
+exit 0
+EOF"""
+ }
+}
+def phone_steps(String device_type, steps) {
+ lock(resource: "", label: device_type, inversePrecedence: true, variable: 'device_ip', quantity: 1) {
+ timeout(time: 60, unit: 'MINUTES') {
+ phone(device_ip, "kill old processes", "pkill -f comma || true")
+ phone(device_ip, "git checkout", readFile("selfdrive/test/setup_device_ci.sh"),)
+ steps.each { item ->
+ phone(device_ip, item[0], item[1])
+ }
+ }
}
+}
+
+pipeline {
+ agent none
environment {
COMMA_JWT = credentials('athena-test-jwt')
+ TEST_DIR = "/data/openpilot"
}
+
stages {
- stage('EON Build/Test') {
+
+ stage('Release Build') {
+ agent {
+ docker {
+ image 'python:3.7.3'
+ args '--user=root'
+ }
+ }
+ when {
+ branch 'devel-staging'
+ }
steps {
- lock(resource: "", label: 'eon', inversePrecedence: true, variable: 'eon_name', quantity: 1){
- timeout(time: 30, unit: 'MINUTES') {
- dir(path: 'release') {
- sh 'pip install paramiko'
- sh 'python remote_build.py'
+ phone_steps("eon-build", [
+ ["build release2-staging and dashcam-staging", "cd release && PUSH=1 ./build_release2.sh"],
+ ])
+ }
+ }
+
+ stage('openpilot tests') {
+ when {
+ not {
+ anyOf {
+ branch 'master-ci'; branch 'devel'; branch 'devel-staging'; branch 'release2'; branch 'release2-staging'; branch 'dashcam'; branch 'dashcam-staging'
+ }
+ }
+ }
+
+
+ stages {
+
+ /*
+ stage('PC tests') {
+ agent {
+ dockerfile {
+ filename 'Dockerfile.openpilot'
+ args '--privileged --shm-size=1G --user=root'
+ }
+ }
+ stages {
+ stage('Build') {
+ steps {
+ sh 'scons -j$(nproc)'
+ }
+ }
+ }
+ post {
+ always {
+ // fix permissions since docker runs as another user
+ sh "chmod -R 777 ."
+ }
+ }
+ }
+ */
+
+ stage('On-device Tests') {
+ agent {
+ docker {
+ image 'python:3.7.3'
+ args '--user=root'
+ }
+ }
+
+ stages {
+ stage('parallel tests') {
+ parallel {
+
+ stage('Devel Build') {
+ environment {
+ CI_PUSH = "${env.BRANCH_NAME == 'master' ? 'master-ci' : ' '}"
+ }
+ steps {
+ phone_steps("eon", [
+ ["build devel", "cd release && CI_PUSH=${env.CI_PUSH} ./build_devel.sh"],
+ ["test openpilot", "nosetests -s selfdrive/test/test_openpilot.py"],
+ ["test cpu usage", "cd selfdrive/test/ && ./test_cpu_usage.py"],
+ ["test car interfaces", "cd selfdrive/car/tests/ && ./test_car_interfaces.py"],
+ ["test spinner build", "cd selfdrive/ui/spinner && make clean && make"],
+ ["test text window build", "cd selfdrive/ui/text && make clean && make"],
+ ])
+ }
+ }
+
+ stage('Replay Tests') {
+ steps {
+ phone_steps("eon2", [
+ ["camerad/modeld replay", "cd selfdrive/test/process_replay && ./camera_replay.py"],
+ ])
+ }
+ }
+
+ stage('HW + Unit Tests') {
+ steps {
+ phone_steps("eon", [
+ ["build cereal", "SCONS_CACHE=1 scons -j4 cereal/"],
+ ["test sounds", "nosetests -s selfdrive/test/test_sounds.py"],
+ ["test boardd loopback", "nosetests -s selfdrive/boardd/tests/test_boardd_loopback.py"],
+ //["test updater", "python installer/updater/test_updater.py"],
+ ])
+ }
+ }
+
+ }
}
}
}
+
}
}
}
diff --git a/Pipfile b/Pipfile
index 9d1f3a3bba..331be0c46f 100644
--- a/Pipfile
+++ b/Pipfile
@@ -6,20 +6,18 @@ verify_ssl = true
[dev-packages]
opencv-python= "*"
ipython = "*"
-networkx = "==2.3"
+networkx = "~=2.3"
azure-core = "*"
azure-common = "*"
-azure-nspkg = "==3.0.2"
-azure-storage-blob = "==2.1.0"
-azure-storage-common = "==2.1.0"
-azure-storage-nspkg = "==3.1.0"
+azure-nspkg = "~=3.0"
+azure-storage-blob = "~=2.1"
+azure-storage-common = "~=2.1"
+azure-storage-nspkg = "~=3.1"
boto = "*"
"boto3" = "*"
control = "*"
datadog = "*"
-dlib = "*"
elasticsearch = "*"
-pycocotools = {git = "https://github.com/cocodataset/cocoapi.git",subdirectory = "PythonAPI"}
gunicorn = "*"
"h5py" = "*"
hexdump = "*"
@@ -41,9 +39,9 @@ redis = "*"
"s2sphere" = "*"
"subprocess32" = "*"
tenacity = "*"
-tensorflow-gpu = "==2.2.0"
+tensorflow = "==2.2"
keras_applications = "*"
-PyMySQL = "==0.9.2"
+PyMySQL = "~=0.9"
Werkzeug = "*"
"backports.lzma" = "*"
Flask-Cors = "*"
@@ -69,9 +67,12 @@ paramiko = "*"
aiohttp = "*"
lru-dict = "*"
scikit-image = "*"
-pygame = "==2.0.0.dev6"
+pygame = "==2.0.0.dev8"
pprofile = "*"
pyprof2calltree = "*"
+pre-commit = "*"
+mypy = "*"
+parameterized = "*"
[packages]
atomicwrites = "*"
@@ -90,7 +91,7 @@ requests = "*"
setproctitle = "*"
six = "*"
smbus2 = "*"
-sympy = "*"
+sympy = "!=1.6.1"
tqdm = "*"
Cython = "*"
PyYAML = "*"
@@ -107,10 +108,10 @@ pylint = "*"
pillow = "*"
scons = "*"
cysignals = "*"
-pycryptodome = "*"
-"Jinja2" = "*"
-PyJWT = "*"
+pycryptodome = "*"
+"Jinja2" = "*"
+PyJWT = "*"
pyserial = "*"
[requires]
-python_version = "3.8.2"
+python_version = "3.8"
diff --git a/Pipfile.lock b/Pipfile.lock
index fbd754bd5f..4a91f0a357 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,11 +1,11 @@
{
"_meta": {
"hash": {
- "sha256": "2fca285af32720e957e1fc42d7c512e9b9a2e93b416602f77d8129d7fd8efedc"
+ "sha256": "d19d5f456b6901c49898a3f7d372874e59b09ac32a57c03a28b0a633fe5d6108"
},
"pipfile-spec": 6,
"requires": {
- "python_version": "3.8.2"
+ "python_version": "3.8"
},
"sources": [
{
@@ -18,11 +18,11 @@
"default": {
"astroid": {
"hashes": [
- "sha256:4c17cea3e592c21b6e222f673868961bad77e1f985cb1694ed077475a89229c1",
- "sha256:d8506842a3faf734b81599c8b98dcc423de863adcc1999248480b18bd31a0f38"
+ "sha256:2f4078c2a41bf377eea06d71c9d2ba4eb8f6b1af2135bec27bbbb7d8f12bb703",
+ "sha256:bc58d83eb610252fd8de6363e39d4f1d0619c894b0ed24603b881c02e64c7386"
],
"markers": "python_version >= '3.5'",
- "version": "==2.4.1"
+ "version": "==2.4.2"
},
"atomicwrites": {
"hashes": [
@@ -34,44 +34,44 @@
},
"certifi": {
"hashes": [
- "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304",
- "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"
+ "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3",
+ "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"
],
- "version": "==2020.4.5.1"
+ "version": "==2020.6.20"
},
"cffi": {
"hashes": [
- "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff",
- "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b",
- "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac",
- "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0",
- "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384",
- "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26",
- "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6",
- "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b",
- "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e",
- "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd",
- "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2",
- "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66",
- "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc",
- "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8",
- "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55",
- "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4",
- "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5",
- "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d",
- "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78",
- "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa",
- "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793",
- "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f",
- "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a",
- "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f",
- "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30",
- "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f",
- "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3",
- "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c"
- ],
- "index": "pypi",
- "version": "==1.14.0"
+ "sha256:267adcf6e68d77ba154334a3e4fc921b8e63cbb38ca00d33d40655d4228502bc",
+ "sha256:26f33e8f6a70c255767e3c3f957ccafc7f1f706b966e110b855bfe944511f1f9",
+ "sha256:3cd2c044517f38d1b577f05927fb9729d3396f1d44d0c659a445599e79519792",
+ "sha256:4a03416915b82b81af5502459a8a9dd62a3c299b295dcdf470877cb948d655f2",
+ "sha256:4ce1e995aeecf7cc32380bc11598bfdfa017d592259d5da00fc7ded11e61d022",
+ "sha256:4f53e4128c81ca3212ff4cf097c797ab44646a40b42ec02a891155cd7a2ba4d8",
+ "sha256:4fa72a52a906425416f41738728268072d5acfd48cbe7796af07a923236bcf96",
+ "sha256:66dd45eb9530e3dde8f7c009f84568bc7cac489b93d04ac86e3111fb46e470c2",
+ "sha256:6923d077d9ae9e8bacbdb1c07ae78405a9306c8fd1af13bfa06ca891095eb995",
+ "sha256:833401b15de1bb92791d7b6fb353d4af60dc688eaa521bd97203dcd2d124a7c1",
+ "sha256:8416ed88ddc057bab0526d4e4e9f3660f614ac2394b5e019a628cdfff3733849",
+ "sha256:892daa86384994fdf4856cb43c93f40cbe80f7f95bb5da94971b39c7f54b3a9c",
+ "sha256:98be759efdb5e5fa161e46d404f4e0ce388e72fbf7d9baf010aff16689e22abe",
+ "sha256:a6d28e7f14ecf3b2ad67c4f106841218c8ab12a0683b1528534a6c87d2307af3",
+ "sha256:b1d6ebc891607e71fd9da71688fcf332a6630b7f5b7f5549e6e631821c0e5d90",
+ "sha256:b2a2b0d276a136146e012154baefaea2758ef1f56ae9f4e01c612b0831e0bd2f",
+ "sha256:b87dfa9f10a470eee7f24234a37d1d5f51e5f5fa9eeffda7c282e2b8f5162eb1",
+ "sha256:bac0d6f7728a9cc3c1e06d4fcbac12aaa70e9379b3025b27ec1226f0e2d404cf",
+ "sha256:c991112622baee0ae4d55c008380c32ecfd0ad417bcd0417ba432e6ba7328caa",
+ "sha256:cda422d54ee7905bfc53ee6915ab68fe7b230cacf581110df4272ee10462aadc",
+ "sha256:d3148b6ba3923c5850ea197a91a42683f946dba7e8eb82dfa211ab7e708de939",
+ "sha256:d6033b4ffa34ef70f0b8086fd4c3df4bf801fee485a8a7d4519399818351aa8e",
+ "sha256:ddff0b2bd7edcc8c82d1adde6dbbf5e60d57ce985402541cd2985c27f7bec2a0",
+ "sha256:e23cb7f1d8e0f93addf0cae3c5b6f00324cccb4a7949ee558d7b6ca973ab8ae9",
+ "sha256:effd2ba52cee4ceff1a77f20d2a9f9bf8d50353c854a282b8760ac15b9833168",
+ "sha256:f90c2267101010de42f7273c94a1f026e56cbc043f9330acd8a80e64300aba33",
+ "sha256:f960375e9823ae6a07072ff7f8a85954e5a6434f97869f50d0e41649a1c8144f",
+ "sha256:fcf32bf76dc25e30ed793145a57426064520890d7c02866eb93d3e4abe516948"
+ ],
+ "index": "pypi",
+ "version": "==1.14.1"
},
"chardet": {
"hashes": [
@@ -100,28 +100,28 @@
},
"cryptography": {
"hashes": [
- "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6",
- "sha256:18452582a3c85b96014b45686af264563e3e5d99d226589f057ace56196ec78b",
- "sha256:1dfa985f62b137909496e7fc182dac687206d8d089dd03eaeb28ae16eec8e7d5",
- "sha256:1e4014639d3d73fbc5ceff206049c5a9a849cefd106a49fa7aaaa25cc0ce35cf",
- "sha256:22e91636a51170df0ae4dcbd250d318fd28c9f491c4e50b625a49964b24fe46e",
- "sha256:3b3eba865ea2754738616f87292b7f29448aec342a7c720956f8083d252bf28b",
- "sha256:651448cd2e3a6bc2bb76c3663785133c40d5e1a8c1a9c5429e4354201c6024ae",
- "sha256:726086c17f94747cedbee6efa77e99ae170caebeb1116353c6cf0ab67ea6829b",
- "sha256:844a76bc04472e5135b909da6aed84360f522ff5dfa47f93e3dd2a0b84a89fa0",
- "sha256:88c881dd5a147e08d1bdcf2315c04972381d026cdb803325c03fe2b4a8ed858b",
- "sha256:96c080ae7118c10fcbe6229ab43eb8b090fccd31a09ef55f83f690d1ef619a1d",
- "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229",
- "sha256:bb1f0281887d89617b4c68e8db9a2c42b9efebf2702a3c5bf70599421a8623e3",
- "sha256:c447cf087cf2dbddc1add6987bbe2f767ed5317adb2d08af940db517dd704365",
- "sha256:c4fd17d92e9d55b84707f4fd09992081ba872d1a0c610c109c18e062e06a2e55",
- "sha256:d0d5aeaedd29be304848f1c5059074a740fa9f6f26b84c5b63e8b29e73dfc270",
- "sha256:daf54a4b07d67ad437ff239c8a4080cfd1cc7213df57d33c97de7b4738048d5e",
- "sha256:e993468c859d084d5579e2ebee101de8f5a27ce8e2159959b6673b418fd8c785",
- "sha256:f118a95c7480f5be0df8afeb9a11bd199aa20afab7a96bcf20409b411a3a85f0"
- ],
- "index": "pypi",
- "version": "==2.9.2"
+ "sha256:0c608ff4d4adad9e39b5057de43657515c7da1ccb1807c3a27d4cf31fc923b4b",
+ "sha256:0cbfed8ea74631fe4de00630f4bb592dad564d57f73150d6f6796a24e76c76cd",
+ "sha256:124af7255ffc8e964d9ff26971b3a6153e1a8a220b9a685dc407976ecb27a06a",
+ "sha256:384d7c681b1ab904fff3400a6909261cae1d0939cc483a68bdedab282fb89a07",
+ "sha256:45741f5499150593178fc98d2c1a9c6722df88b99c821ad6ae298eff0ba1ae71",
+ "sha256:4b9303507254ccb1181d1803a2080a798910ba89b1a3c9f53639885c90f7a756",
+ "sha256:4d355f2aee4a29063c10164b032d9fa8a82e2c30768737a2fd56d256146ad559",
+ "sha256:51e40123083d2f946794f9fe4adeeee2922b581fa3602128ce85ff813d85b81f",
+ "sha256:8713ddb888119b0d2a1462357d5946b8911be01ddbf31451e1d07eaa5077a261",
+ "sha256:8e924dbc025206e97756e8903039662aa58aa9ba357d8e1d8fc29e3092322053",
+ "sha256:8ecef21ac982aa78309bb6f092d1677812927e8b5ef204a10c326fc29f1367e2",
+ "sha256:8ecf9400d0893836ff41b6f977a33972145a855b6efeb605b49ee273c5e6469f",
+ "sha256:9367d00e14dee8d02134c6c9524bb4bd39d4c162456343d07191e2a0b5ec8b3b",
+ "sha256:a09fd9c1cca9a46b6ad4bea0a1f86ab1de3c0c932364dbcf9a6c2a5eeb44fa77",
+ "sha256:ab49edd5bea8d8b39a44b3db618e4783ef84c19c8b47286bf05dfdb3efb01c83",
+ "sha256:bea0b0468f89cdea625bb3f692cd7a4222d80a6bdafd6fb923963f2b9da0e15f",
+ "sha256:bec7568c6970b865f2bcebbe84d547c52bb2abadf74cefce396ba07571109c67",
+ "sha256:ce82cc06588e5cbc2a7df3c8a9c778f2cb722f56835a23a68b5a7264726bb00c",
+ "sha256:dea0ba7fe6f9461d244679efa968d215ea1f989b9c1957d7f10c21e5c7c09ad6"
+ ],
+ "index": "pypi",
+ "version": "==3.0"
},
"cysignals": {
"hashes": [
@@ -132,50 +132,50 @@
},
"cython": {
"hashes": [
- "sha256:00faa77500ca2f865fd7f3126f86e77de3ec0d855dd6cf92fc85b57ebed11655",
- "sha256:14e218a93d4f2e43e0063a5a0f7f26fe1783d5d20700216c5c4ff092c4553488",
- "sha256:179ad5569dc101e3e0d9d04305f9a5e03fbf8acf9d93fb543340f8c1a8fb054b",
- "sha256:20cdf3f918c46355128d7c7cb041872ba2863cc11313972c6e390bd3dad968ba",
- "sha256:2a98c9f852b266f0b9a147da4b6699cf6da24b817375f74d51986312373689ab",
- "sha256:3950ae725472ae47bfb41c6bfdb3869a8ac27b5f30405f599a51398512afa224",
- "sha256:4dbb58f963f6283b31b4ddac44e4f684527b06923efdec72ecb54e70ee91c766",
- "sha256:4e8d351ee840a4e491f8f0a64da19923ada0ce09d2d818bce0ae6ce1b6837aeb",
- "sha256:4f35752adfd4855d39e38bf08eb6d02f7aa88b1bb420ab86e6d2e37ccd7c88c2",
- "sha256:5c501742a92cbcef8f3c21d1dcba9c073b37f1218af3586957901730ac6b6665",
- "sha256:6361588cb1d82875bcfbad83d7dd66c442099759f895cf547995f00601f9caf2",
- "sha256:719eddf050a1c8b0abbd74b0c388523cf618c3d9fe3bf20a350f4eafa43776e6",
- "sha256:785d6e88a3bb10ce6425d23f0a740a21b0bfc9e8d371fea7edba0eaa0ec57d96",
- "sha256:788192badd3b1ebb1a72a5c6cc2a07b692ca4c1c1fe4431fdd3c0e439e2c0a6d",
- "sha256:7c8ac5bc9726ccb1a1cce1af4ceb7589228db6c57ada3bfcd461075abe3a6a7b",
- "sha256:7cec6bd82fd92f85790908fdc7a43a8a5442606e6d771d5b32a1ab8a39ad1a65",
- "sha256:7d597733ad0e7fc545df39100ee3b24290ce35586466dee4fa6018d4b8815d72",
- "sha256:809896928abce18e7c91a28b2705473ca4f15b9a53f433495845a882e15c09d8",
- "sha256:8135cc7de72805833a118e7c8a255daddd35875d17ea21f6c356200b0fa4b732",
- "sha256:86ae455b1dd7041b4b8a15499fe72f3d3f990f78a794deb799ee2ef7db389ca0",
- "sha256:8ef49cafea89d99ffc2cf37af2f0f2b7d219080574f14a422f701bcaa85c7167",
- "sha256:96d18413a33aa5ce51a5554615ba01e3fdb26126d8678459330d052f0bdf60ec",
- "sha256:a5ebd8fe5a3d97924bd89d449914d1c5b6d084f4b124a4eb28e4412d09fb0f20",
- "sha256:b19a1aa98192d44d7254613a1f9c382ef381deb79289f2ff446d1447d19085aa",
- "sha256:b6f7d2cf2f6b246fd04696d6d346489628f94f72a4988682ea0591b632370a1f",
- "sha256:c56f658ab6f387619a3668cd78cf2d3459324d9ea3cb39cce4d72ef5bce8f318",
- "sha256:c68f3015cbb0f5bc402829bad0a6b907889413f2e28cc0873dc1443de0f1a808",
- "sha256:c78fd0bdf5915f4df730298e6cc7197e4c6aa5285d7c37491366a38125b3e0ab",
- "sha256:dcfee6312cf8f4f4839bae22f323a0e885c4237e2187202ab12def8a5460ca4c",
- "sha256:e146b4b4ed4937a40e9e5c27b264adfce4ae4b7640d46eeffd3eef123b0170a2",
- "sha256:ea75bbc076d4a5605d04c72c8c7a933f51473b0bcecd79295256b9ecd75cca49",
- "sha256:f7b20838f2534ad0d231c4c6e09acbdd40fb995a9671bb05839f7879093ec5e3",
- "sha256:fce2e7f500b1456f96d5b8ceefba243cae7018ad8b3f791e62c20a0f0fbba71c"
- ],
- "index": "pypi",
- "version": "==0.29.17"
+ "sha256:0ac10bf476476a9f7ef61ec6e44c280ef434473124ad31d3132b720f7b0e8d2a",
+ "sha256:0e25c209c75df8785480dcef85db3d36c165dbc0f4c503168e8763eb735704f2",
+ "sha256:171b9f70ceafcec5852089d0f9c1e75b0d554f46c882cd4e2e4acaba9bd7d148",
+ "sha256:23f3a00b843a19de8bb4468b087db5b413a903213f67188729782488d67040e0",
+ "sha256:2922e3031ba9ebbe7cb9200b585cc33b71d66023d78450dcb883f824f4969371",
+ "sha256:31c71a615f38401b0dc1f2a5a9a6c421ffd8908c4cd5bbedc4014c1b876488e8",
+ "sha256:473df5d5e400444a36ed81c6596f56a5b52a3481312d0a48d68b777790f730ae",
+ "sha256:497841897942f734b0abc2dead2d4009795ee992267a70a23485fd0e937edc0b",
+ "sha256:539e59949aab4955c143a468810123bf22d3e8556421e1ce2531ed4893914ca0",
+ "sha256:540b3bee0711aac2e99bda4fa0a46dbcd8c74941666bfc1ef9236b1a64eeffd9",
+ "sha256:57ead89128dee9609119c93d3926c7a2add451453063147900408a50144598c6",
+ "sha256:5c4276fdcbccdf1e3c1756c7aeb8395e9a36874fa4d30860e7694f43d325ae13",
+ "sha256:5da187bebe38030325e1c0b5b8a804d489410be2d384c0ef3ba39493c67eb51e",
+ "sha256:5e545a48f919e40079b0efe7b0e081c74b96f9ef25b9c1ff4cdbd95764426b58",
+ "sha256:603b9f1b8e93e8b494d3e89320c410679e21018e48b6cbc77280f5db71f17dc0",
+ "sha256:695a6bcaf9e12b1e471dfce96bbecf22a1487adc2ac6106b15960a2b51b97f5d",
+ "sha256:715294cd2246b39a8edca464a8366eb635f17213e4a6b9e74e52d8b877a8cb63",
+ "sha256:856c7fb31d247ce713d60116375e1f8153d0291ab5e92cca7d8833a524ba9991",
+ "sha256:8c6e25e9cc4961bb2abb1777c6fa9d0fa2d9b014beb3276cebe69996ff162b78",
+ "sha256:9207fdedc7e789a3dcaca628176b80c82fbed9ae0997210738cbb12536a56699",
+ "sha256:93f5fed1c9445fb7afe20450cdaf94b0e0356d47cc75008105be89c6a2e417b1",
+ "sha256:9ce5e5209f8406ffc2b058b1293cce7a954911bb7991e623564d489197c9ba30",
+ "sha256:a0674f246ad5e1571ef29d4c5ec1d6ecabe9e6c424ad0d6fee46b914d5d24d69",
+ "sha256:b2f9172e4d6358f33ecce6a4339b5960f9f83eab67ea244baa812737793826b7",
+ "sha256:b8a8a31b9e8860634adbca30fea1d0c7f08e208b3d7611f3e580e5f20992e5d7",
+ "sha256:b8d8497091c1dc8705d1575c71e908a93b1f127a174b2d472020f3d84263ac28",
+ "sha256:c4b78356074fcaac04ecb4de289f11d506e438859877670992ece11f9c90f37b",
+ "sha256:c541b2b49c6638f2b5beb9316726db84a8d1c132bf31b942dae1f9c7f6ad3b92",
+ "sha256:c8435959321cf8aec867bbad54b83b7fb8343204b530d85d9ea7a1f5329d5ac2",
+ "sha256:ccb77faeaad99e99c6c444d04862c6cf604204fe0a07d4c8f9cbf2c9012d7d5a",
+ "sha256:e272ed97d20b026f4f25a012b25d7d7672a60e4f72b9ca385239d693cd91b2d5",
+ "sha256:e57acb89bd55943c8d8bf813763d20b9099cc7165c0f16b707631a7654be9cad",
+ "sha256:e93acd1f603a0c1786e0841f066ae7cef014cf4750e3cd06fd03cfdf46361419"
+ ],
+ "index": "pypi",
+ "version": "==0.29.21"
},
"flake8": {
"hashes": [
- "sha256:6c1193b0c3f853ef763969238f6c81e9e63ace9d024518edc020d5f1d6d93195",
- "sha256:ea6623797bf9a52f4c9577d780da0bb17d65f870213f7b5bcc9fca82540c31d5"
+ "sha256:15e351d19611c887e482fb960eae4d44845013cc142d42896e9862f775d8cf5c",
+ "sha256:f04b9fcbac03b0a3e58c0ab3a0ecc462e023a9faf046d57794184028123aa208"
],
"index": "pypi",
- "version": "==3.8.1"
+ "version": "==3.8.3"
},
"flask": {
"hashes": [
@@ -202,11 +202,11 @@
},
"idna": {
"hashes": [
- "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
- "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"
+ "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
+ "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==2.9"
+ "version": "==2.10"
},
"isort": {
"hashes": [
@@ -342,76 +342,84 @@
},
"numpy": {
"hashes": [
- "sha256:00d7b54c025601e28f468953d065b9b121ddca7fff30bed7be082d3656dd798d",
- "sha256:02ec9582808c4e48be4e93cd629c855e644882faf704bc2bd6bbf58c08a2a897",
- "sha256:0e6f72f7bb08f2f350ed4408bb7acdc0daba637e73bce9f5ea2b207039f3af88",
- "sha256:1be2e96314a66f5f1ce7764274327fd4fb9da58584eaff00b5a5221edefee7d6",
- "sha256:2466fbcf23711ebc5daa61d28ced319a6159b260a18839993d871096d66b93f7",
- "sha256:2b573fcf6f9863ce746e4ad00ac18a948978bb3781cffa4305134d31801f3e26",
- "sha256:3f0dae97e1126f529ebb66f3c63514a0f72a177b90d56e4bce8a0b5def34627a",
- "sha256:50fb72bcbc2cf11e066579cb53c4ca8ac0227abb512b6cbc1faa02d1595a2a5d",
- "sha256:57aea170fb23b1fd54fa537359d90d383d9bf5937ee54ae8045a723caa5e0961",
- "sha256:709c2999b6bd36cdaf85cf888d8512da7433529f14a3689d6e37ab5242e7add5",
- "sha256:7d59f21e43bbfd9a10953a7e26b35b6849d888fc5a331fa84a2d9c37bd9fe2a2",
- "sha256:904b513ab8fbcbdb062bed1ce2f794ab20208a1b01ce9bd90776c6c7e7257032",
- "sha256:96dd36f5cdde152fd6977d1bbc0f0561bccffecfde63cd397c8e6033eb66baba",
- "sha256:9933b81fecbe935e6a7dc89cbd2b99fea1bf362f2790daf9422a7bb1dc3c3085",
- "sha256:bbcc85aaf4cd84ba057decaead058f43191cc0e30d6bc5d44fe336dc3d3f4509",
- "sha256:dccd380d8e025c867ddcb2f84b439722cf1f23f3a319381eac45fd077dee7170",
- "sha256:e22cd0f72fc931d6abc69dc7764484ee20c6a60b0d0fee9ce0426029b1c1bdae",
- "sha256:ed722aefb0ebffd10b32e67f48e8ac4c5c4cf5d3a785024fdf0e9eb17529cd9d",
- "sha256:efb7ac5572c9a57159cf92c508aad9f856f1cb8e8302d7fdb99061dbe52d712c",
- "sha256:efdba339fffb0e80fcc19524e4fdbda2e2b5772ea46720c44eaac28096d60720",
- "sha256:f22273dd6a403ed870207b853a856ff6327d5cbce7a835dfa0645b3fc00273ec"
- ],
- "index": "pypi",
- "version": "==1.18.4"
+ "sha256:082f8d4dd69b6b688f64f509b91d482362124986d98dc7dc5f5e9f9b9c3bb983",
+ "sha256:1bc0145999e8cb8aed9d4e65dd8b139adf1919e521177f198529687dbf613065",
+ "sha256:309cbcfaa103fc9a33ec16d2d62569d541b79f828c382556ff072442226d1968",
+ "sha256:3673c8b2b29077f1b7b3a848794f8e11f401ba0b71c49fbd26fb40b71788b132",
+ "sha256:480fdd4dbda4dd6b638d3863da3be82873bba6d32d1fc12ea1b8486ac7b8d129",
+ "sha256:56ef7f56470c24bb67fb43dae442e946a6ce172f97c69f8d067ff8550cf782ff",
+ "sha256:5a936fd51049541d86ccdeef2833cc89a18e4d3808fe58a8abeb802665c5af93",
+ "sha256:5b6885c12784a27e957294b60f97e8b5b4174c7504665333c5e94fbf41ae5d6a",
+ "sha256:667c07063940e934287993366ad5f56766bc009017b4a0fe91dbd07960d0aba7",
+ "sha256:7ed448ff4eaffeb01094959b19cbaf998ecdee9ef9932381420d514e446601cd",
+ "sha256:8343bf67c72e09cfabfab55ad4a43ce3f6bf6e6ced7acf70f45ded9ebb425055",
+ "sha256:92feb989b47f83ebef246adabc7ff3b9a59ac30601c3f6819f8913458610bdcc",
+ "sha256:935c27ae2760c21cd7354402546f6be21d3d0c806fffe967f745d5f2de5005a7",
+ "sha256:aaf42a04b472d12515debc621c31cf16c215e332242e7a9f56403d814c744624",
+ "sha256:b12e639378c741add21fbffd16ba5ad25c0a1a17cf2b6fe4288feeb65144f35b",
+ "sha256:b1cca51512299841bf69add3b75361779962f9cee7d9ee3bb446d5982e925b69",
+ "sha256:b8456987b637232602ceb4d663cb34106f7eb780e247d51a260b84760fd8f491",
+ "sha256:b9792b0ac0130b277536ab8944e7b754c69560dac0415dd4b2dbd16b902c8954",
+ "sha256:c9591886fc9cbe5532d5df85cb8e0cc3b44ba8ce4367bd4cf1b93dc19713da72",
+ "sha256:cf1347450c0b7644ea142712619533553f02ef23f92f781312f6a3553d031fc7",
+ "sha256:de8b4a9b56255797cbddb93281ed92acbc510fb7b15df3f01bd28f46ebc4edae",
+ "sha256:e1b1dc0372f530f26a03578ac75d5e51b3868b9b76cd2facba4c9ee0eb252ab1",
+ "sha256:e45f8e981a0ab47103181773cc0a54e650b2aef8c7b6cd07405d0fa8d869444a",
+ "sha256:e4f6d3c53911a9d103d8ec9518190e52a8b945bab021745af4939cfc7c0d4a9e",
+ "sha256:ed8a311493cf5480a2ebc597d1e177231984c818a86875126cfd004241a73c3e",
+ "sha256:ef71a1d4fd4858596ae80ad1ec76404ad29701f8ca7cdcebc50300178db14dfc"
+ ],
+ "index": "pypi",
+ "version": "==1.19.1"
},
"pillow": {
"hashes": [
- "sha256:04766c4930c174b46fd72d450674612ab44cca977ebbcc2dde722c6933290107",
- "sha256:0e2a3bceb0fd4e0cb17192ae506d5f082b309ffe5fc370a5667959c9b2f85fa3",
- "sha256:0f01e63c34f0e1e2580cc0b24e86a5ccbbfa8830909a52ee17624c4193224cd9",
- "sha256:12e4bad6bddd8546a2f9771485c7e3d2b546b458ae8ff79621214119ac244523",
- "sha256:1f694e28c169655c50bb89a3fa07f3b854d71eb47f50783621de813979ba87f3",
- "sha256:3d25dd8d688f7318dca6d8cd4f962a360ee40346c15893ae3b95c061cdbc4079",
- "sha256:4b02b9c27fad2054932e89f39703646d0c543f21d3cc5b8e05434215121c28cd",
- "sha256:70e3e0d99a0dcda66283a185f80697a9b08806963c6149c8e6c5f452b2aa59c0",
- "sha256:9744350687459234867cbebfe9df8f35ef9e1538f3e729adbd8fde0761adb705",
- "sha256:a0b49960110bc6ff5fead46013bcb8825d101026d466f3a4de3476defe0fb0dd",
- "sha256:ae2b270f9a0b8822b98655cb3a59cdb1bd54a34807c6c56b76dd2e786c3b7db3",
- "sha256:b37bb3bd35edf53125b0ff257822afa6962649995cbdfde2791ddb62b239f891",
- "sha256:b532bcc2f008e96fd9241177ec580829dee817b090532f43e54074ecffdcd97f",
- "sha256:b67a6c47ed963c709ed24566daa3f95a18f07d3831334da570c71da53d97d088",
- "sha256:b943e71c2065ade6fef223358e56c167fc6ce31c50bc7a02dd5c17ee4338e8ac",
- "sha256:ccc9ad2460eb5bee5642eaf75a0438d7f8887d484490d5117b98edd7f33118b7",
- "sha256:d23e2aa9b969cf9c26edfb4b56307792b8b374202810bd949effd1c6e11ebd6d",
- "sha256:eaa83729eab9c60884f362ada982d3a06beaa6cc8b084cf9f76cae7739481dfa",
- "sha256:ee94fce8d003ac9fd206496f2707efe9eadcb278d94c271f129ab36aa7181344",
- "sha256:f455efb7a98557412dc6f8e463c1faf1f1911ec2432059fa3e582b6000fc90e2",
- "sha256:f46e0e024346e1474083c729d50de909974237c72daca05393ee32389dabe457",
- "sha256:f54be399340aa602066adb63a86a6a5d4f395adfdd9da2b9a0162ea808c7b276",
- "sha256:f784aad988f12c80aacfa5b381ec21fd3f38f851720f652b9f33facc5101cf4d"
- ],
- "index": "pypi",
- "version": "==7.1.2"
+ "sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f",
+ "sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8",
+ "sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad",
+ "sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f",
+ "sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae",
+ "sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d",
+ "sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5",
+ "sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b",
+ "sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8",
+ "sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233",
+ "sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6",
+ "sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727",
+ "sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f",
+ "sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38",
+ "sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4",
+ "sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626",
+ "sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d",
+ "sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6",
+ "sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63",
+ "sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f",
+ "sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41",
+ "sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1",
+ "sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d",
+ "sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9",
+ "sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a",
+ "sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce"
+ ],
+ "index": "pypi",
+ "version": "==7.2.0"
},
"psutil": {
"hashes": [
- "sha256:1413f4158eb50e110777c4f15d7c759521703bd6beb58926f1d562da40180058",
- "sha256:298af2f14b635c3c7118fd9183843f4e73e681bb6f01e12284d4d70d48a60953",
- "sha256:60b86f327c198561f101a92be1995f9ae0399736b6eced8f24af41ec64fb88d4",
- "sha256:685ec16ca14d079455892f25bd124df26ff9137664af445563c1bd36629b5e0e",
- "sha256:73f35ab66c6c7a9ce82ba44b1e9b1050be2a80cd4dcc3352cc108656b115c74f",
- "sha256:75e22717d4dbc7ca529ec5063000b2b294fc9a367f9c9ede1f65846c7955fd38",
- "sha256:a02f4ac50d4a23253b68233b07e7cdb567bd025b982d5cf0ee78296990c22d9e",
- "sha256:d008ddc00c6906ec80040d26dc2d3e3962109e40ad07fd8a12d0284ce5e0e4f8",
- "sha256:d84029b190c8a66a946e28b4d3934d2ca1528ec94764b180f7d6ea57b0e75e26",
- "sha256:e2d0c5b07c6fe5a87fa27b7855017edb0d52ee73b71e6ee368fae268605cc3f5",
- "sha256:f344ca230dd8e8d5eee16827596f1c22ec0876127c28e800d7ae20ed44c4b310"
+ "sha256:0ee3c36428f160d2d8fce3c583a0353e848abb7de9732c50cf3356dd49ad63f8",
+ "sha256:10512b46c95b02842c225f58fa00385c08fa00c68bac7da2d9a58ebe2c517498",
+ "sha256:4080869ed93cce662905b029a1770fe89c98787e543fa7347f075ade761b19d6",
+ "sha256:5e9d0f26d4194479a13d5f4b3798260c20cecf9ac9a461e718eb59ea520a360c",
+ "sha256:66c18ca7680a31bf16ee22b1d21b6397869dda8059dbdb57d9f27efa6615f195",
+ "sha256:68d36986ded5dac7c2dcd42f2682af1db80d4bce3faa126a6145c1637e1b559f",
+ "sha256:90990af1c3c67195c44c9a889184f84f5b2320dce3ee3acbd054e3ba0b4a7beb",
+ "sha256:a5b120bb3c0c71dfe27551f9da2f3209a8257a178ed6c628a819037a8df487f1",
+ "sha256:d8a82162f23c53b8525cf5f14a355f5d1eea86fa8edde27287dd3a98399e4fdf",
+ "sha256:f2018461733b23f308c298653c8903d32aaad7873d25e1d228765e91ae42c3f2",
+ "sha256:ff1977ba1a5f71f89166d5145c3da1cea89a0fdb044075a12c720ee9123ec818"
],
"index": "pypi",
- "version": "==5.7.0"
+ "version": "==5.7.2"
},
"pycapnp": {
"hashes": [
@@ -438,39 +446,39 @@
},
"pycryptodome": {
"hashes": [
- "sha256:07024fc364869eae8d6ac0d316e089956e6aeffe42dbdcf44fe1320d96becf7f",
- "sha256:09b6d6bcc01a4eb1a2b4deeff5aa602a108ec5aed8ac75ae554f97d1d7f0a5ad",
- "sha256:0e10f352ccbbcb5bb2dc4ecaf106564e65702a717d72ab260f9ac4c19753cfc2",
- "sha256:1f4752186298caf2e9ff5354f2e694d607ca7342aa313a62005235d46e28cf04",
- "sha256:2fbc472e0b567318fe2052281d5a8c0ae70099b446679815f655e9fbc18c3a65",
- "sha256:3ec3dc2f80f71fd0c955ce48b81bfaf8914c6f63a41a738f28885a1c4892968a",
- "sha256:426c188c83c10df71f053e04b4003b1437bae5cb37606440e498b00f160d71d0",
- "sha256:626c0a1d4d83ec6303f970a17158114f75c3ba1736f7f2983f7b40a265861bd8",
- "sha256:767ad0fb5d23efc36a4d5c2fc608ac603f3de028909bcf59abc943e0d0bc5a36",
- "sha256:7ac729d9091ed5478af2b4a4f44f5335a98febbc008af619e4569a59fe503e40",
- "sha256:83295a3fb5cf50c48631eb5b440cb5e9832d8c14d81d1d45f4497b67a9987de8",
- "sha256:8be56bde3312e022d9d1d6afa124556460ad5c844c2fc63642f6af723c098d35",
- "sha256:8f06556a8f7ea7b1e42eff39726bb0dca1c251205debae64e6eebea3cd7b438a",
- "sha256:9230fcb5d948c3fb40049bace4d33c5d254f8232c2c0bba05d2570aea3ba4520",
- "sha256:9378c309aec1f8cd8bad361ed0816a440151b97a2a3f6ffdaba1d1a1fb76873a",
- "sha256:9977086e0f93adb326379897437373871b80501e1d176fec63c7f46fb300c862",
- "sha256:9a94fca11fdc161460bd8659c15b6adef45c1b20da86402256eaf3addfaab324",
- "sha256:9c739b7795ccf2ef1fdad8d44e539a39ad300ee6786e804ea7f0c6a786eb5343",
- "sha256:b1e332587b3b195542e77681389c296e1837ca01240399d88803a075447d3557",
- "sha256:c109a26a21f21f695d369ff9b87f5d43e0d6c768d8384e10bc74142bed2e092e",
- "sha256:c818dc1f3eace93ee50c2b6b5c2becf7c418fa5dd1ba6fc0ef7db279ea21d5e4",
- "sha256:cff31f5a8977534f255f729d5d2467526f2b10563a30bbdade92223e0bf264bd",
- "sha256:d4f94368ce2d65873a87ad867eb3bf63f4ba81eb97a9ee66d38c2b71ce5a7439",
- "sha256:d61b012baa8c2b659e9890011358455c0019a4108536b811602d2f638c40802a",
- "sha256:d6e1bc5c94873bec742afe2dfadce0d20445b18e75c47afc0c115b19e5dd38dd",
- "sha256:ea83bcd9d6c03248ebd46e71ac313858e0afd5aa2fa81478c0e653242f3eb476",
- "sha256:ed5761b37615a1f222c5345bbf45272ae2cf8c7dff88a4f53a1e9f977cbb6d95",
- "sha256:f011cd0062e54658b7086a76f8cf0f4222812acc66e219e196ea2d0a8849d0ed",
- "sha256:f1add21b6d179179b3c177c33d18a2186a09cc0d3af41ff5ed3f377360b869f2",
- "sha256:f655addaaaa9974108d4808f4150652589cada96074c87115c52e575bfcd87d5"
- ],
- "index": "pypi",
- "version": "==3.9.7"
+ "sha256:02e51e1d5828d58f154896ddfd003e2e7584869c275e5acbe290443575370fba",
+ "sha256:03d5cca8618620f45fd40f827423f82b86b3a202c8d44108601b0f5f56b04299",
+ "sha256:0e24171cf01021bc5dc17d6a9d4f33a048f09d62cc3f62541e95ef104588bda4",
+ "sha256:132a56abba24e2e06a479d8e5db7a48271a73a215f605017bbd476d31f8e71c1",
+ "sha256:1e655746f539421d923fd48df8f6f40b3443d80b75532501c0085b64afed9df5",
+ "sha256:2b998dc45ef5f4e5cf5248a6edfcd8d8e9fb5e35df8e4259b13a1b10eda7b16b",
+ "sha256:360955eece2cd0fa694a708d10303c6abd7b39614fa2547b6bd245da76198beb",
+ "sha256:39ef9fb52d6ec7728fce1f1693cb99d60ce302aeebd59bcedea70ca3203fda60",
+ "sha256:4350a42028240c344ee855f032c7d4ad6ff4f813bfbe7121547b7dc579ecc876",
+ "sha256:50348edd283afdccddc0938cdc674484533912ba8a99a27c7bfebb75030aa856",
+ "sha256:54bdedd28476dea8a3cd86cb67c0df1f0e3d71cae8022354b0f879c41a3d27b2",
+ "sha256:55eb61aca2c883db770999f50d091ff7c14016f2769ad7bca3d9b75d1d7c1b68",
+ "sha256:6276478ada411aca97c0d5104916354b3d740d368407912722bd4d11aa9ee4c2",
+ "sha256:67dcad1b8b201308586a8ca2ffe89df1e4f731d5a4cdd0610cc4ea790351c739",
+ "sha256:709b9f144d23e290b9863121d1ace14a72e01f66ea9c903fbdc690520dfdfcf0",
+ "sha256:8063a712fba642f78d3c506b0896846601b6de7f5c3d534e388ad0cc07f5a149",
+ "sha256:80d57177a0b7c14d4594c62bbb47fe2f6309ad3b0a34348a291d570925c97a82",
+ "sha256:a207231a52426de3ff20f5608f0687261a3329d97a036c51f7d4c606a6f30c23",
+ "sha256:abc2e126c9490e58a36a0f83516479e781d83adfb134576a5cbe5c6af2a3e93c",
+ "sha256:b56638d58a3a4be13229c6a815cd448f9e3ce40c00880a5398471b42ee86f50e",
+ "sha256:bcd5b8416e73e4b0d48afba3704d8c826414764dafaed7a1a93c442188d90ccc",
+ "sha256:bec2bcdf7c9ce7f04d718e51887f3b05dc5c1cfaf5d2c2e9065ecddd1b2f6c9a",
+ "sha256:c8bf40cf6e281a4378e25846924327e728a887e8bf0ee83b2604a0f4b61692e8",
+ "sha256:d8074c8448cfd0705dfa71ca333277fce9786d0b9cac75d120545de6253f996a",
+ "sha256:dd302b6ae3965afeb5ef1b0d92486f986c0e65183cd7835973f0b593800590e6",
+ "sha256:de6e1cd75677423ff64712c337521e62e3a7a4fc84caabbd93207752e831a85a",
+ "sha256:ef39c98d9b8c0736d91937d193653e47c3b19ddf4fc3bccdc5e09aaa4b0c5d21",
+ "sha256:f521178e5a991ffd04182ed08f552daca1affcb826aeda0e1945cd989a9d4345",
+ "sha256:f78a68c2c820e4731e510a2df3eef0322f24fde1781ced970bf497b6c7d92982",
+ "sha256:fbe65d5cfe04ff2f7684160d50f5118bdefb01e3af4718eeb618bfed40f19d94"
+ ],
+ "index": "pypi",
+ "version": "==3.9.8"
},
"pyflakes": {
"hashes": [
@@ -490,11 +498,11 @@
},
"pylint": {
"hashes": [
- "sha256:b95e31850f3af163c2283ed40432f053acbc8fc6eba6a069cb518d9dbf71848c",
- "sha256:dd506acce0427e9e08fb87274bcaa953d38b50a58207170dbf5b36cf3e16957b"
+ "sha256:7dd78437f2d8d019717dbf287772d0b2dbdfd13fc016aa7faa08d67bccc46adc",
+ "sha256:d0ece7d223fe422088b0e8f13fa0a1e8eb745ebffcb8ed53d3e95394b6101a1c"
],
"index": "pypi",
- "version": "==2.5.2"
+ "version": "==2.5.3"
},
"pyserial": {
"hashes": [
@@ -531,37 +539,37 @@
},
"pyzmq": {
"hashes": [
- "sha256:07fb8fe6826a229dada876956590135871de60dbc7de5a18c3bcce2ed1f03c98",
- "sha256:13a5638ab24d628a6ade8f794195e1a1acd573496c3b85af2f1183603b7bf5e0",
- "sha256:15b4cb21118f4589c4db8be4ac12b21c8b4d0d42b3ee435d47f686c32fe2e91f",
- "sha256:21f7d91f3536f480cb2c10d0756bfa717927090b7fb863e6323f766e5461ee1c",
- "sha256:2a88b8fabd9cc35bd59194a7723f3122166811ece8b74018147a4ed8489e6421",
- "sha256:342fb8a1dddc569bc361387782e8088071593e7eaf3e3ecf7d6bd4976edff112",
- "sha256:4ee0bfd82077a3ff11c985369529b12853a4064320523f8e5079b630f9551448",
- "sha256:54aa24fd60c4262286fc64ca632f9e747c7cc3a3a1144827490e1dc9b8a3a960",
- "sha256:58688a2dfa044fad608a8e70ba8d019d0b872ec2acd75b7b5e37da8905605891",
- "sha256:5b99c2ae8089ef50223c28bac57510c163bfdff158c9e90764f812b94e69a0e6",
- "sha256:5b9d21fc56c8aacd2e6d14738021a9d64f3f69b30578a99325a728e38a349f85",
- "sha256:5f1f2eb22aab606f808163eb1d537ac9a0ba4283fbeb7a62eb48d9103cf015c2",
- "sha256:6ca519309703e95d55965735a667809bbb65f52beda2fdb6312385d3e7a6d234",
- "sha256:87c78f6936e2654397ca2979c1d323ee4a889eef536cc77a938c6b5be33351a7",
- "sha256:8952f6ba6ae598e792703f3134af5a01af8f5c7cf07e9a148f05a12b02412cea",
- "sha256:931339ac2000d12fe212e64f98ce291e81a7ec6c73b125f17cf08415b753c087",
- "sha256:956775444d01331c7eb412c5fb9bb62130dfaac77e09f32764ea1865234e2ca9",
- "sha256:97b6255ae77328d0e80593681826a0479cb7bac0ba8251b4dd882f5145a2293a",
- "sha256:aaa8b40b676576fd7806839a5de8e6d5d1b74981e6376d862af6c117af2a3c10",
- "sha256:af0c02cf49f4f9eedf38edb4f3b6bb621d83026e7e5d76eb5526cc5333782fd6",
- "sha256:b08780e3a55215873b3b8e6e7ca8987f14c902a24b6ac081b344fd430d6ca7cd",
- "sha256:ba6f24431b569aec674ede49cad197cad59571c12deed6ad8e3c596da8288217",
- "sha256:bafd651b557dd81d89bd5f9c678872f3e7b7255c1c751b78d520df2caac80230",
- "sha256:bfff5ffff051f5aa47ba3b379d87bd051c3196b0c8a603e8b7ed68a6b4f217ec",
- "sha256:cf5d689ba9513b9753959164cf500079383bc18859f58bf8ce06d8d4bef2b054",
- "sha256:dcbc3f30c11c60d709c30a213dc56e88ac016fe76ac6768e64717bd976072566",
- "sha256:f9d7e742fb0196992477415bb34366c12e9bb9a0699b8b3f221ff93b213d7bec",
- "sha256:faee2604f279d31312bc455f3d024f160b6168b9c1dde22bf62d8c88a4deca8e"
- ],
- "index": "pypi",
- "version": "==19.0.1"
+ "sha256:00dca814469436455399660247d74045172955459c0bd49b54a540ce4d652185",
+ "sha256:046b92e860914e39612e84fa760fc3f16054d268c11e0e25dcb011fb1bc6a075",
+ "sha256:09d24a80ccb8cbda1af6ed8eb26b005b6743e58e9290566d2a6841f4e31fa8e0",
+ "sha256:0a422fc290d03958899743db091f8154958410fc76ce7ee0ceb66150f72c2c97",
+ "sha256:276ad604bffd70992a386a84bea34883e696a6b22e7378053e5d3227321d9702",
+ "sha256:296540a065c8c21b26d63e3cea2d1d57902373b16e4256afe46422691903a438",
+ "sha256:29d51279060d0a70f551663bc592418bcad7f4be4eea7b324f6dd81de05cb4c1",
+ "sha256:36ab114021c0cab1a423fe6689355e8f813979f2c750968833b318c1fa10a0fd",
+ "sha256:3fa6debf4bf9412e59353defad1f8035a1e68b66095a94ead8f7a61ae90b2675",
+ "sha256:5120c64646e75f6db20cc16b9a94203926ead5d633de9feba4f137004241221d",
+ "sha256:59f1e54627483dcf61c663941d94c4af9bf4163aec334171686cdaee67974fe5",
+ "sha256:5d9fc809aa8d636e757e4ced2302569d6e60e9b9c26114a83f0d9d6519c40493",
+ "sha256:654d3e06a4edc566b416c10293064732516cf8871a4522e0a2ba00cc2a2e600c",
+ "sha256:720d2b6083498a9281eaee3f2927486e9fe02cd16d13a844f2e95217f243efea",
+ "sha256:73483a2caaa0264ac717af33d6fb3f143d8379e60a422730ee8d010526ce1913",
+ "sha256:8a6ada5a3f719bf46a04ba38595073df8d6b067316c011180102ba2a1925f5b5",
+ "sha256:8b66b94fe6243d2d1d89bca336b2424399aac57932858b9a30309803ffc28112",
+ "sha256:99cc0e339a731c6a34109e5c4072aaa06d8e32c0b93dc2c2d90345dd45fa196c",
+ "sha256:a7e7f930039ee0c4c26e4dfee015f20bd6919cd8b97c9cd7afbde2923a5167b6",
+ "sha256:ab0d01148d13854de716786ca73701012e07dff4dfbbd68c4e06d8888743526e",
+ "sha256:c1a31cd42905b405530e92bdb70a8a56f048c8a371728b8acf9d746ecd4482c0",
+ "sha256:c20dd60b9428f532bc59f2ef6d3b1029a28fc790d408af82f871a7db03e722ff",
+ "sha256:c36ffe1e5aa35a1af6a96640d723d0d211c5f48841735c2aa8d034204e87eb87",
+ "sha256:c40fbb2b9933369e994b837ee72193d6a4c35dfb9a7c573257ef7ff28961272c",
+ "sha256:d46fb17f5693244de83e434648b3dbb4f4b0fec88415d6cbab1c1452b6f2ae17",
+ "sha256:e36f12f503511d72d9bdfae11cadbadca22ff632ff67c1b5459f69756a029c19",
+ "sha256:f1a25a61495b6f7bb986accc5b597a3541d9bd3ef0016f50be16dbb32025b302",
+ "sha256:fa411b1d8f371d3a49d31b0789eb6da2537dadbb2aef74a43aa99a78195c3f76"
+ ],
+ "index": "pypi",
+ "version": "==19.0.2"
},
"raven": {
"hashes": [
@@ -573,19 +581,19 @@
},
"requests": {
"hashes": [
- "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
- "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
+ "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b",
+ "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"
],
"index": "pypi",
- "version": "==2.23.0"
+ "version": "==2.24.0"
},
"scons": {
"hashes": [
- "sha256:0f860678cd96fc943ff2294389b0f33cbe51080801591497bc652e72237f0176",
- "sha256:8aaa483c303efeb678e6f7c776c8444a482f8ddc3ad891f8b6cdd35264da9a1f"
+ "sha256:722ed104b5c624ecdc89bd4e02b094d2b14d99d47b5d0501961e47f579a2007c",
+ "sha256:9b4696a806fb73f402fbf5e37ab0e8b6cd0dcef990a91210d7ed4aacbcc5231d"
],
"index": "pypi",
- "version": "==3.1.2"
+ "version": "==4.0.1"
},
"setproctitle": {
"hashes": [
@@ -597,11 +605,11 @@
},
"six": {
"hashes": [
- "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
- "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
+ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
+ "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
"index": "pypi",
- "version": "==1.14.0"
+ "version": "==1.15.0"
},
"smbus2": {
"hashes": [
@@ -612,35 +620,34 @@
},
"sympy": {
"hashes": [
- "sha256:4880d3a351558063bd89febda302f220dc4b88de393bba81fa6539a3966f03fa",
- "sha256:d77901d748287d15281f5ffe5b0fef62dd38f357c2b827c44ff07f35695f4e7e"
+ "sha256:7af1e11e9fcb72362c47a481dc010e518cfcb60a594d1ee8bd268f86ea7d6cbf",
+ "sha256:9769e3d2952e211b1245f1d0dfdbfbdde1f7779a3953832b7dd2b88a21ca6cc6"
],
"index": "pypi",
- "version": "==1.5.1"
+ "version": "==1.6"
},
"toml": {
"hashes": [
- "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
- "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e",
- "sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"
+ "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f",
+ "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"
],
- "version": "==0.10.0"
+ "version": "==0.10.1"
},
"tqdm": {
"hashes": [
- "sha256:4733c4a10d0f2a4d098d801464bdaf5240c7dadd2a7fde4ee93b0a0efd9fb25e",
- "sha256:acdafb20f51637ca3954150d0405ff1a7edde0ff19e38fb99a80a66210d2a28f"
+ "sha256:1a336d2b829be50e46b84668691e0a2719f26c97c62846298dd5ae2937e4d5cf",
+ "sha256:564d632ea2b9cb52979f7956e093e831c28d441c11751682f84c86fc46e4fd21"
],
"index": "pypi",
- "version": "==4.46.0"
+ "version": "==4.48.2"
},
"urllib3": {
"hashes": [
- "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527",
- "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"
+ "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a",
+ "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"
],
"index": "pypi",
- "version": "==1.25.9"
+ "version": "==1.25.10"
},
"utm": {
"hashes": [
@@ -681,19 +688,19 @@
},
"adal": {
"hashes": [
- "sha256:2ae7e02cea4552349fed6d8c9912da400f7e643fc30098defe0dcd01945e7c54",
- "sha256:a74ff45b88db18d3d3d0c50d0d2d6d411866648f457bef4be714ba0b8e30d515"
+ "sha256:7a15d22b1ee7ce1be92441199958748982feba6b7dec35fbf60f9b607bad1bc0",
+ "sha256:b332316f54d947f39acd9628e7d61d90f6e54d413d6f97025a51482c96bac6bc"
],
- "version": "==1.2.3"
+ "version": "==1.2.4"
},
"aenum": {
"hashes": [
- "sha256:284ddb976413d97239a932d7e5202ba58d66e5dbd81531bf3033ebb36ec30b23",
- "sha256:a4334cabf47c167d44ab5a6198837b80deec5d5bad1b5cf70c966c3a330260e8",
- "sha256:d2bb6ea7586aaae889d3a5c332eafa851eeffe6e7068807c79b6c86c4326b938"
+ "sha256:81828d1fbe20b6b188d75b21a0fa936d7d929d839ef843ef385d9c2a97082864",
+ "sha256:85adabd63183d283250bf7acd9fa23c7e45b1c8d1efbb84b233160f3c438dc18",
+ "sha256:bcb4fd350d36af336b6b5898e5d89f76344621d9c1b2de69c81acf1d3e6b1145"
],
"index": "pypi",
- "version": "==2.2.3"
+ "version": "==2.2.4"
},
"aiohttp": {
"hashes": [
@@ -729,18 +736,39 @@
},
"argcomplete": {
"hashes": [
- "sha256:5ae7b601be17bf38a749ec06aa07fb04e7b6b5fc17906948dc1866e7facf3740",
- "sha256:890bdd1fcbb973ed73db241763e78b6d958580e588c2910b508c770a59ef37d7"
+ "sha256:2fbe5ed09fd2c1d727d4199feca96569a5b50d44c71b16da9c742201f7cc295c",
+ "sha256:91dc7f9c7f6281d5a0dce5e73d2e33283aaef083495c13974a7dd197a1cdc949"
],
- "version": "==1.11.1"
+ "version": "==1.12.0"
+ },
+ "argon2-cffi": {
+ "hashes": [
+ "sha256:05a8ac07c7026542377e38389638a8a1e9b78f1cd8439cd7493b39f08dd75fbf",
+ "sha256:0bf066bc049332489bb2d75f69216416329d9dc65deee127152caeb16e5ce7d5",
+ "sha256:18dee20e25e4be86680b178b35ccfc5d495ebd5792cd00781548d50880fee5c5",
+ "sha256:392c3c2ef91d12da510cfb6f9bae52512a4552573a9e27600bdb800e05905d2b",
+ "sha256:57358570592c46c420300ec94f2ff3b32cbccd10d38bdc12dc6979c4a8484fbc",
+ "sha256:6678bb047373f52bcff02db8afab0d2a77d83bde61cfecea7c5c62e2335cb203",
+ "sha256:6ea92c980586931a816d61e4faf6c192b4abce89aa767ff6581e6ddc985ed003",
+ "sha256:77e909cc756ef81d6abb60524d259d959bab384832f0c651ed7dcb6e5ccdbb78",
+ "sha256:7d455c802727710e9dfa69b74ccaab04568386ca17b0ad36350b622cd34606fe",
+ "sha256:9bee3212ba4f560af397b6d7146848c32a800652301843df06b9e8f68f0f7361",
+ "sha256:9dfd5197852530294ecb5795c97a823839258dfd5eb9420233c7cfedec2058f2",
+ "sha256:b160416adc0f012fb1f12588a5e6954889510f82f698e23ed4f4fa57f12a0647",
+ "sha256:ba7209b608945b889457f949cc04c8e762bed4fe3fec88ae9a6b7765ae82e496",
+ "sha256:cc0e028b209a5483b6846053d5fd7165f460a1f14774d79e632e75e7ae64b82b",
+ "sha256:d8029b2d3e4b4cea770e9e5a0104dd8fa185c1724a0f01528ae4826a6d25f97d",
+ "sha256:da7f0445b71db6d3a72462e04f36544b0de871289b0bc8a7cc87c0f5ec7079fa"
+ ],
+ "version": "==20.1.0"
},
"astroid": {
"hashes": [
- "sha256:4c17cea3e592c21b6e222f673868961bad77e1f985cb1694ed077475a89229c1",
- "sha256:d8506842a3faf734b81599c8b98dcc423de863adcc1999248480b18bd31a0f38"
+ "sha256:2f4078c2a41bf377eea06d71c9d2ba4eb8f6b1af2135bec27bbbb7d8f12bb703",
+ "sha256:bc58d83eb610252fd8de6363e39d4f1d0619c894b0ed24603b881c02e64c7386"
],
"markers": "python_version >= '3.5'",
- "version": "==2.4.1"
+ "version": "==2.4.2"
},
"astunparse": {
"hashes": [
@@ -767,11 +795,11 @@
},
"azure-cli-core": {
"hashes": [
- "sha256:5b2d3952f7edab1a34d7421b5a7ff1aabf32d9fca6614bdac5ec9938e64b7caa",
- "sha256:668d45eef11ff155969c205b730d044d18d4729bf70d127f85cfd85ed69bff98"
+ "sha256:2f07ae6f4fa729398e2959f7f94424f753718f01c7301ae79156a5e72fb49a30",
+ "sha256:c81fc3fe245b183f7fb249f9dc46f1c3269d1621387c34a628c200d05c6593e2"
],
"index": "pypi",
- "version": "==2.5.1"
+ "version": "==2.10.1"
},
"azure-cli-nspkg": {
"hashes": [
@@ -799,11 +827,11 @@
},
"azure-core": {
"hashes": [
- "sha256:2b7613b37ff6503312e5ec7c9ce2efab8fa0dbfe4c6c1d3bf91bab51db9bd6dc",
- "sha256:afa6a6ae577859392e1ed3acb024bf5bddeb1bbb67f3191c35c587505ff431a0"
+ "sha256:2d1aade2795ea0ac2a903af940c3e0dfe75d25351ec4fc44edf747e97d703dfb",
+ "sha256:a66da240a287f447f9867f54ba09ea235895cec13ea38c5f490ce4eedefdd75c"
],
"index": "pypi",
- "version": "==1.5.0"
+ "version": "==1.7.0"
},
"azure-mgmt-core": {
"hashes": [
@@ -814,10 +842,10 @@
},
"azure-mgmt-resource": {
"hashes": [
- "sha256:055e85a4053a987bf427653e75f537c750ecc27c0e7c74623a67cb859689b5a6",
- "sha256:dc12f7998e2c1fd4088a8da5f02936c2985ceb7acbe994571c8b3778f26a7501"
+ "sha256:33ae072d0f60b804eda68c4396a73a7154005c88abf85d42c40a8991d0aa4eb9",
+ "sha256:9be7fcdf586f24acb799a799cf5e9363e9323ca0ce54cca63ab505f69fa0fddd"
],
- "version": "==9.0.0"
+ "version": "==10.1.0"
},
"azure-nspkg": {
"hashes": [
@@ -854,10 +882,10 @@
},
"backcall": {
"hashes": [
- "sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4",
- "sha256:bbbf4b1e5cd2bdb08f915895b51081c041bac22394fdfcfdfbe9f14b77c08bf2"
+ "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e",
+ "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"
],
- "version": "==0.1.0"
+ "version": "==0.2.0"
},
"backports.lzma": {
"hashes": [
@@ -871,6 +899,7 @@
"sha256:0258f143f3de96b7c14f762c770f5fc56ccd72f8a1857a451c1cd9a655d9ac89",
"sha256:0b0069c752ec14172c5f78208f1863d7ad6755a6fae6fe76ec2c80d13be41e42",
"sha256:19a4b72a6ae5bb467fea018b825f0a7d917789bcfe893e53f15c92805d187294",
+ "sha256:436a487dec749bca7e6e72498a75a5fa2433bda13bac91d023e18df9089ae0b8",
"sha256:5432dd7b34107ae8ed6c10a71b4397f1c853bd39a4d6ffa7e35f40584cffd161",
"sha256:6305557019906466fc42dbc53b46da004e72fd7a551c044a827e572c82191752",
"sha256:69361315039878c0680be456640f8705d76cb4a3a3fe1e057e0f261b74be4b31",
@@ -908,67 +937,75 @@
},
"boto3": {
"hashes": [
- "sha256:b81a6296134aec4d48319e5d25e47c2abcea2cd13ddd160f95b692e56c6ab9b7",
- "sha256:c347350521e8138a42b7c877bb87ba32842405d7bc7fd86b29745abc60b9e83d"
+ "sha256:3aad418cb5a20f522f3d0267caefb5582324f5af60fe093ace12e69847cf72cd",
+ "sha256:d33af62c691c0078326970ec4f09bef4b8822bdfa7eca3a6c26b6b4c016c32d7"
],
"index": "pypi",
- "version": "==1.13.8"
+ "version": "==1.14.38"
},
"botocore": {
"hashes": [
- "sha256:68eb83d97a8ecdbf271c17989280bc9a533269d4ee983d2ef80289e2333042da",
- "sha256:8263bba760c3f24aeb0651936b24798ba8a172828afdccf8bee5ca6d5d7c4b9c"
+ "sha256:37de221e9b9ba8a3225387d7a4d5313d55ff78e32a2986cce682cb21418b9ee3",
+ "sha256:e14b778d58640049d22c587c30d466bcc3432102f5715ffbe0bec2858b13a1b9"
],
- "version": "==1.16.8"
+ "version": "==1.17.38"
},
"cachetools": {
"hashes": [
- "sha256:1d057645db16ca7fe1f3bd953558897603d6f0b9c51ed9d11eb4d071ec4e2aab",
- "sha256:de5d88f87781602201cde465d3afe837546663b168e8b39df67411b0bf10cefc"
+ "sha256:513d4ff98dd27f85743a8dc0e92f55ddb1b49e060c2d5961512855cda2c01a98",
+ "sha256:bbaa39c3dede00175df2dc2b03d0cf18dd2d32a7de7beb68072d13043c9edb20"
],
"markers": "python_version ~= '3.5'",
- "version": "==4.1.0"
+ "version": "==4.1.1"
},
"certifi": {
"hashes": [
- "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304",
- "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"
+ "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3",
+ "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"
],
- "version": "==2020.4.5.1"
+ "version": "==2020.6.20"
},
"cffi": {
"hashes": [
- "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff",
- "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b",
- "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac",
- "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0",
- "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384",
- "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26",
- "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6",
- "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b",
- "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e",
- "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd",
- "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2",
- "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66",
- "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc",
- "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8",
- "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55",
- "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4",
- "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5",
- "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d",
- "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78",
- "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa",
- "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793",
- "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f",
- "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a",
- "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f",
- "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30",
- "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f",
- "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3",
- "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c"
- ],
- "index": "pypi",
- "version": "==1.14.0"
+ "sha256:267adcf6e68d77ba154334a3e4fc921b8e63cbb38ca00d33d40655d4228502bc",
+ "sha256:26f33e8f6a70c255767e3c3f957ccafc7f1f706b966e110b855bfe944511f1f9",
+ "sha256:3cd2c044517f38d1b577f05927fb9729d3396f1d44d0c659a445599e79519792",
+ "sha256:4a03416915b82b81af5502459a8a9dd62a3c299b295dcdf470877cb948d655f2",
+ "sha256:4ce1e995aeecf7cc32380bc11598bfdfa017d592259d5da00fc7ded11e61d022",
+ "sha256:4f53e4128c81ca3212ff4cf097c797ab44646a40b42ec02a891155cd7a2ba4d8",
+ "sha256:4fa72a52a906425416f41738728268072d5acfd48cbe7796af07a923236bcf96",
+ "sha256:66dd45eb9530e3dde8f7c009f84568bc7cac489b93d04ac86e3111fb46e470c2",
+ "sha256:6923d077d9ae9e8bacbdb1c07ae78405a9306c8fd1af13bfa06ca891095eb995",
+ "sha256:833401b15de1bb92791d7b6fb353d4af60dc688eaa521bd97203dcd2d124a7c1",
+ "sha256:8416ed88ddc057bab0526d4e4e9f3660f614ac2394b5e019a628cdfff3733849",
+ "sha256:892daa86384994fdf4856cb43c93f40cbe80f7f95bb5da94971b39c7f54b3a9c",
+ "sha256:98be759efdb5e5fa161e46d404f4e0ce388e72fbf7d9baf010aff16689e22abe",
+ "sha256:a6d28e7f14ecf3b2ad67c4f106841218c8ab12a0683b1528534a6c87d2307af3",
+ "sha256:b1d6ebc891607e71fd9da71688fcf332a6630b7f5b7f5549e6e631821c0e5d90",
+ "sha256:b2a2b0d276a136146e012154baefaea2758ef1f56ae9f4e01c612b0831e0bd2f",
+ "sha256:b87dfa9f10a470eee7f24234a37d1d5f51e5f5fa9eeffda7c282e2b8f5162eb1",
+ "sha256:bac0d6f7728a9cc3c1e06d4fcbac12aaa70e9379b3025b27ec1226f0e2d404cf",
+ "sha256:c991112622baee0ae4d55c008380c32ecfd0ad417bcd0417ba432e6ba7328caa",
+ "sha256:cda422d54ee7905bfc53ee6915ab68fe7b230cacf581110df4272ee10462aadc",
+ "sha256:d3148b6ba3923c5850ea197a91a42683f946dba7e8eb82dfa211ab7e708de939",
+ "sha256:d6033b4ffa34ef70f0b8086fd4c3df4bf801fee485a8a7d4519399818351aa8e",
+ "sha256:ddff0b2bd7edcc8c82d1adde6dbbf5e60d57ce985402541cd2985c27f7bec2a0",
+ "sha256:e23cb7f1d8e0f93addf0cae3c5b6f00324cccb4a7949ee558d7b6ca973ab8ae9",
+ "sha256:effd2ba52cee4ceff1a77f20d2a9f9bf8d50353c854a282b8760ac15b9833168",
+ "sha256:f90c2267101010de42f7273c94a1f026e56cbc043f9330acd8a80e64300aba33",
+ "sha256:f960375e9823ae6a07072ff7f8a85954e5a6434f97869f50d0e41649a1c8144f",
+ "sha256:fcf32bf76dc25e30ed793145a57426064520890d7c02866eb93d3e4abe516948"
+ ],
+ "index": "pypi",
+ "version": "==1.14.1"
+ },
+ "cfgv": {
+ "hashes": [
+ "sha256:32e43d604bbe7896fe7c248a9c2276447dbef840feb28fe20494f62af110211d",
+ "sha256:cf22deb93d4bcf92f345a5c3cd39d3d41d6340adc60c78bbbd6588c384fda6a1"
+ ],
+ "markers": "python_version >= '3.6.1'",
+ "version": "==3.2.0"
},
"chardet": {
"hashes": [
@@ -1002,65 +1039,68 @@
},
"coverage": {
"hashes": [
- "sha256:00f1d23f4336efc3b311ed0d807feb45098fc86dee1ca13b3d6768cdab187c8a",
- "sha256:01333e1bd22c59713ba8a79f088b3955946e293114479bbfc2e37d522be03355",
- "sha256:0cb4be7e784dcdc050fc58ef05b71aa8e89b7e6636b99967fadbdba694cf2b65",
- "sha256:0e61d9803d5851849c24f78227939c701ced6704f337cad0a91e0972c51c1ee7",
- "sha256:1601e480b9b99697a570cea7ef749e88123c04b92d84cedaa01e117436b4a0a9",
- "sha256:2742c7515b9eb368718cd091bad1a1b44135cc72468c731302b3d641895b83d1",
- "sha256:2d27a3f742c98e5c6b461ee6ef7287400a1956c11421eb574d843d9ec1f772f0",
- "sha256:402e1744733df483b93abbf209283898e9f0d67470707e3c7516d84f48524f55",
- "sha256:5c542d1e62eece33c306d66fe0a5c4f7f7b3c08fecc46ead86d7916684b36d6c",
- "sha256:5f2294dbf7875b991c381e3d5af2bcc3494d836affa52b809c91697449d0eda6",
- "sha256:6402bd2fdedabbdb63a316308142597534ea8e1895f4e7d8bf7476c5e8751fef",
- "sha256:66460ab1599d3cf894bb6baee8c684788819b71a5dc1e8fa2ecc152e5d752019",
- "sha256:782caea581a6e9ff75eccda79287daefd1d2631cc09d642b6ee2d6da21fc0a4e",
- "sha256:79a3cfd6346ce6c13145731d39db47b7a7b859c0272f02cdb89a3bdcbae233a0",
- "sha256:7a5bdad4edec57b5fb8dae7d3ee58622d626fd3a0be0dfceda162a7035885ecf",
- "sha256:8fa0cbc7ecad630e5b0f4f35b0f6ad419246b02bc750de7ac66db92667996d24",
- "sha256:a027ef0492ede1e03a8054e3c37b8def89a1e3c471482e9f046906ba4f2aafd2",
- "sha256:a3f3654d5734a3ece152636aad89f58afc9213c6520062db3978239db122f03c",
- "sha256:a82b92b04a23d3c8a581fc049228bafde988abacba397d57ce95fe95e0338ab4",
- "sha256:acf3763ed01af8410fc36afea23707d4ea58ba7e86a8ee915dfb9ceff9ef69d0",
- "sha256:adeb4c5b608574a3d647011af36f7586811a2c1197c861aedb548dd2453b41cd",
- "sha256:b83835506dfc185a319031cf853fa4bb1b3974b1f913f5bb1a0f3d98bdcded04",
- "sha256:bb28a7245de68bf29f6fb199545d072d1036a1917dca17a1e75bbb919e14ee8e",
- "sha256:bf9cb9a9fd8891e7efd2d44deb24b86d647394b9705b744ff6f8261e6f29a730",
- "sha256:c317eaf5ff46a34305b202e73404f55f7389ef834b8dbf4da09b9b9b37f76dd2",
- "sha256:dbe8c6ae7534b5b024296464f387d57c13caa942f6d8e6e0346f27e509f0f768",
- "sha256:de807ae933cfb7f0c7d9d981a053772452217df2bf38e7e6267c9cbf9545a796",
- "sha256:dead2ddede4c7ba6cb3a721870f5141c97dc7d85a079edb4bd8d88c3ad5b20c7",
- "sha256:dec5202bfe6f672d4511086e125db035a52b00f1648d6407cc8e526912c0353a",
- "sha256:e1ea316102ea1e1770724db01998d1603ed921c54a86a2efcb03428d5417e489",
- "sha256:f90bfc4ad18450c80b024036eaf91e4a246ae287701aaa88eaebebf150868052"
- ],
- "index": "pypi",
- "version": "==5.1"
+ "sha256:098a703d913be6fbd146a8c50cc76513d726b022d170e5e98dc56d958fd592fb",
+ "sha256:16042dc7f8e632e0dcd5206a5095ebd18cb1d005f4c89694f7f8aafd96dd43a3",
+ "sha256:1adb6be0dcef0cf9434619d3b892772fdb48e793300f9d762e480e043bd8e716",
+ "sha256:27ca5a2bc04d68f0776f2cdcb8bbd508bbe430a7bf9c02315cd05fb1d86d0034",
+ "sha256:28f42dc5172ebdc32622a2c3f7ead1b836cdbf253569ae5673f499e35db0bac3",
+ "sha256:2fcc8b58953d74d199a1a4d633df8146f0ac36c4e720b4a1997e9b6327af43a8",
+ "sha256:304fbe451698373dc6653772c72c5d5e883a4aadaf20343592a7abb2e643dae0",
+ "sha256:30bc103587e0d3df9e52cd9da1dd915265a22fad0b72afe54daf840c984b564f",
+ "sha256:40f70f81be4d34f8d491e55936904db5c527b0711b2a46513641a5729783c2e4",
+ "sha256:4186fc95c9febeab5681bc3248553d5ec8c2999b8424d4fc3a39c9cba5796962",
+ "sha256:46794c815e56f1431c66d81943fa90721bb858375fb36e5903697d5eef88627d",
+ "sha256:4869ab1c1ed33953bb2433ce7b894a28d724b7aa76c19b11e2878034a4e4680b",
+ "sha256:4f6428b55d2916a69f8d6453e48a505c07b2245653b0aa9f0dee38785939f5e4",
+ "sha256:52f185ffd3291196dc1aae506b42e178a592b0b60a8610b108e6ad892cfc1bb3",
+ "sha256:538f2fd5eb64366f37c97fdb3077d665fa946d2b6d95447622292f38407f9258",
+ "sha256:64c4f340338c68c463f1b56e3f2f0423f7b17ba6c3febae80b81f0e093077f59",
+ "sha256:675192fca634f0df69af3493a48224f211f8db4e84452b08d5fcebb9167adb01",
+ "sha256:700997b77cfab016533b3e7dbc03b71d33ee4df1d79f2463a318ca0263fc29dd",
+ "sha256:8505e614c983834239f865da2dd336dcf9d72776b951d5dfa5ac36b987726e1b",
+ "sha256:962c44070c281d86398aeb8f64e1bf37816a4dfc6f4c0f114756b14fc575621d",
+ "sha256:9e536783a5acee79a9b308be97d3952b662748c4037b6a24cbb339dc7ed8eb89",
+ "sha256:9ea749fd447ce7fb1ac71f7616371f04054d969d412d37611716721931e36efd",
+ "sha256:a34cb28e0747ea15e82d13e14de606747e9e484fb28d63c999483f5d5188e89b",
+ "sha256:a3ee9c793ffefe2944d3a2bd928a0e436cd0ac2d9e3723152d6fd5398838ce7d",
+ "sha256:aab75d99f3f2874733946a7648ce87a50019eb90baef931698f96b76b6769a46",
+ "sha256:b1ed2bdb27b4c9fc87058a1cb751c4df8752002143ed393899edb82b131e0546",
+ "sha256:b360d8fd88d2bad01cb953d81fd2edd4be539df7bfec41e8753fe9f4456a5082",
+ "sha256:b8f58c7db64d8f27078cbf2a4391af6aa4e4767cc08b37555c4ae064b8558d9b",
+ "sha256:c1bbb628ed5192124889b51204de27c575b3ffc05a5a91307e7640eff1d48da4",
+ "sha256:c2ff24df02a125b7b346c4c9078c8936da06964cc2d276292c357d64378158f8",
+ "sha256:c890728a93fffd0407d7d37c1e6083ff3f9f211c83b4316fae3778417eab9811",
+ "sha256:c96472b8ca5dc135fb0aa62f79b033f02aa434fb03a8b190600a5ae4102df1fd",
+ "sha256:ce7866f29d3025b5b34c2e944e66ebef0d92e4a4f2463f7266daa03a1332a651",
+ "sha256:e26c993bd4b220429d4ec8c1468eca445a4064a61c74ca08da7429af9bc53bb0"
+ ],
+ "index": "pypi",
+ "version": "==5.2.1"
},
"cryptography": {
"hashes": [
- "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6",
- "sha256:18452582a3c85b96014b45686af264563e3e5d99d226589f057ace56196ec78b",
- "sha256:1dfa985f62b137909496e7fc182dac687206d8d089dd03eaeb28ae16eec8e7d5",
- "sha256:1e4014639d3d73fbc5ceff206049c5a9a849cefd106a49fa7aaaa25cc0ce35cf",
- "sha256:22e91636a51170df0ae4dcbd250d318fd28c9f491c4e50b625a49964b24fe46e",
- "sha256:3b3eba865ea2754738616f87292b7f29448aec342a7c720956f8083d252bf28b",
- "sha256:651448cd2e3a6bc2bb76c3663785133c40d5e1a8c1a9c5429e4354201c6024ae",
- "sha256:726086c17f94747cedbee6efa77e99ae170caebeb1116353c6cf0ab67ea6829b",
- "sha256:844a76bc04472e5135b909da6aed84360f522ff5dfa47f93e3dd2a0b84a89fa0",
- "sha256:88c881dd5a147e08d1bdcf2315c04972381d026cdb803325c03fe2b4a8ed858b",
- "sha256:96c080ae7118c10fcbe6229ab43eb8b090fccd31a09ef55f83f690d1ef619a1d",
- "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229",
- "sha256:bb1f0281887d89617b4c68e8db9a2c42b9efebf2702a3c5bf70599421a8623e3",
- "sha256:c447cf087cf2dbddc1add6987bbe2f767ed5317adb2d08af940db517dd704365",
- "sha256:c4fd17d92e9d55b84707f4fd09992081ba872d1a0c610c109c18e062e06a2e55",
- "sha256:d0d5aeaedd29be304848f1c5059074a740fa9f6f26b84c5b63e8b29e73dfc270",
- "sha256:daf54a4b07d67ad437ff239c8a4080cfd1cc7213df57d33c97de7b4738048d5e",
- "sha256:e993468c859d084d5579e2ebee101de8f5a27ce8e2159959b6673b418fd8c785",
- "sha256:f118a95c7480f5be0df8afeb9a11bd199aa20afab7a96bcf20409b411a3a85f0"
- ],
- "index": "pypi",
- "version": "==2.9.2"
+ "sha256:0c608ff4d4adad9e39b5057de43657515c7da1ccb1807c3a27d4cf31fc923b4b",
+ "sha256:0cbfed8ea74631fe4de00630f4bb592dad564d57f73150d6f6796a24e76c76cd",
+ "sha256:124af7255ffc8e964d9ff26971b3a6153e1a8a220b9a685dc407976ecb27a06a",
+ "sha256:384d7c681b1ab904fff3400a6909261cae1d0939cc483a68bdedab282fb89a07",
+ "sha256:45741f5499150593178fc98d2c1a9c6722df88b99c821ad6ae298eff0ba1ae71",
+ "sha256:4b9303507254ccb1181d1803a2080a798910ba89b1a3c9f53639885c90f7a756",
+ "sha256:4d355f2aee4a29063c10164b032d9fa8a82e2c30768737a2fd56d256146ad559",
+ "sha256:51e40123083d2f946794f9fe4adeeee2922b581fa3602128ce85ff813d85b81f",
+ "sha256:8713ddb888119b0d2a1462357d5946b8911be01ddbf31451e1d07eaa5077a261",
+ "sha256:8e924dbc025206e97756e8903039662aa58aa9ba357d8e1d8fc29e3092322053",
+ "sha256:8ecef21ac982aa78309bb6f092d1677812927e8b5ef204a10c326fc29f1367e2",
+ "sha256:8ecf9400d0893836ff41b6f977a33972145a855b6efeb605b49ee273c5e6469f",
+ "sha256:9367d00e14dee8d02134c6c9524bb4bd39d4c162456343d07191e2a0b5ec8b3b",
+ "sha256:a09fd9c1cca9a46b6ad4bea0a1f86ab1de3c0c932364dbcf9a6c2a5eeb44fa77",
+ "sha256:ab49edd5bea8d8b39a44b3db618e4783ef84c19c8b47286bf05dfdb3efb01c83",
+ "sha256:bea0b0468f89cdea625bb3f692cd7a4222d80a6bdafd6fb923963f2b9da0e15f",
+ "sha256:bec7568c6970b865f2bcebbe84d547c52bb2abadf74cefce396ba07571109c67",
+ "sha256:ce82cc06588e5cbc2a7df3c8a9c778f2cb722f56835a23a68b5a7264726bb00c",
+ "sha256:dea0ba7fe6f9461d244679efa968d215ea1f989b9c1957d7f10c21e5c7c09ad6"
+ ],
+ "index": "pypi",
+ "version": "==3.0"
},
"cycler": {
"hashes": [
@@ -1071,11 +1111,11 @@
},
"datadog": {
"hashes": [
- "sha256:398c612f8fb8e1988be897fda920ffb3b8a1ec70d430730e3b71a269df31b486",
- "sha256:3fe197587db49d808ba88e40f431fb2d256be3c428419ac2984609d67fd66bce"
+ "sha256:401cd1dcf2d5de05786016a1c790bff28d1428d12ae1dbe11485f9cb5502939b",
+ "sha256:b5ebf25e88cf6891ff26a4a82898ae5ff23d712ad5501e1043113bd0a1903c16"
],
"index": "pypi",
- "version": "==0.36.0"
+ "version": "==0.38.0"
},
"decorator": {
"hashes": [
@@ -1100,12 +1140,12 @@
"index": "pypi",
"version": "==0.8.1"
},
- "dlib": {
+ "distlib": {
"hashes": [
- "sha256:d0eeaca07bc4c75973ad0f739a541d8fa4003af778f0dc1c2c595d470823819a"
+ "sha256:8c09de2c67b3e7deef7184574fc060ab8a793e7adbb183d942c389c8b13c52fb",
+ "sha256:edf6116872c863e1aa9d5bb7cb5e05a022c519a4594dc703843343a9ddd9bff1"
],
- "index": "pypi",
- "version": "==19.19.0"
+ "version": "==0.3.1"
},
"docutils": {
"hashes": [
@@ -1118,11 +1158,11 @@
},
"elasticsearch": {
"hashes": [
- "sha256:d228b2d37ac0865f7631335268172dbdaa426adec1da3ed006dddf05134f89c8",
- "sha256:f4bb05cfe55cf369bdcb4d86d0129d39d66a91fd9517b13cd4e4231fbfcf5c81"
+ "sha256:2ffbd746fc7d2db08e5ede29c822483705f29c4bf43b0875c238637d5d843d44",
+ "sha256:92b534931865a186906873f75ae0b91808ff5036b0f2b9269eb5f6dc09644b55"
],
"index": "pypi",
- "version": "==7.6.0"
+ "version": "==7.8.1"
},
"entrypoints": {
"hashes": [
@@ -1161,6 +1201,13 @@
"index": "pypi",
"version": "==1.1.26"
},
+ "filelock": {
+ "hashes": [
+ "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59",
+ "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"
+ ],
+ "version": "==3.0.12"
+ },
"flask": {
"hashes": [
"sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060",
@@ -1179,11 +1226,11 @@
},
"flask-socketio": {
"hashes": [
- "sha256:5969e1d4ead37ec9164f82779ec86239f0f394a08b20477d2056903010920f36",
- "sha256:7f9b54ac9cd92e28a657c58f51943d97e76b988840c8795784e7b2bafb13103f"
+ "sha256:3668675bf7763c5b5f56689d439f07356e89c0a52e0c9e9cd3cc08563c07b252",
+ "sha256:36c1d5765010d1f4e4f05b4cc9c20c289d9dc70698c88d1addd0afcfedc5b062"
],
"index": "pypi",
- "version": "==4.3.0"
+ "version": "==4.3.1"
},
"future": {
"hashes": [
@@ -1202,11 +1249,11 @@
},
"geoalchemy2": {
"hashes": [
- "sha256:379b0fc4ca5f9b5ef625719f47e22c9b8abd347aa78344e85f99d32594cfccd4",
- "sha256:ec2a6e9919b522631803ac5922e88b701081da7e5d56a68f10ff263f6592d552"
+ "sha256:3b83654db15ed807a7bdb2e7dd1c787a47cfc3e4fb92a0558685001fbb7342da",
+ "sha256:d9336f17df3e7a10f94d1ea2488dcfb97a8bc23fe7f5edea425ddab553534b0a"
],
"index": "pypi",
- "version": "==0.7.0"
+ "version": "==0.8.4"
},
"git-pylint-commit-hook": {
"hashes": [
@@ -1217,11 +1264,11 @@
},
"google-auth": {
"hashes": [
- "sha256:4942ab1ff530e740866571c0416fb5a7dc9ec53233a8f8dff63e8cd7371003d1",
- "sha256:82d32f6601f35309c95d5917bcdf72f3ec193c7f46c79e433b8d76ccbe68e21d"
+ "sha256:2f34dd810090d0d4c9d5787c4ad7b4413d1fbfb941e13682c7a2298d3b6cdcc8",
+ "sha256:ce1fb80b5c6d3dd038babcc43e221edeafefc72d983b3dc28b67b996f76f00b9"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==1.14.3"
+ "version": "==1.20.1"
},
"google-auth-oauthlib": {
"hashes": [
@@ -1240,39 +1287,47 @@
},
"grpcio": {
"hashes": [
- "sha256:085bbf7fd0070b8d65e84aa32979f17cfe624d27b5ce23955ef770c19d2d9623",
- "sha256:0ae207a47ec0ad66eb1f53a27d566674d13a236c62ced409891335318ea9b8c5",
- "sha256:0c130204ff5de0b9f041bf3126db0d29369d69883592e4b0d3c19868ba0ced7e",
- "sha256:0ef6b380a588c2c6b29c6cfa0ba7f5d367beb33d5504bcc68658fa241ad498d2",
- "sha256:16e1edb367763ea08d0994d4635ec05f4f8db9db59c39304b061097e3b93df43",
- "sha256:16f5523dacae5aaeda4cf900da7e980747f663298c38c18eb4e5317704aa007a",
- "sha256:181b5078cf568f37915b8a118afcef5fc9f3128c59c38998ed93e7dd793e3928",
- "sha256:245564713cb4ac7bccb0f11be63781beb62299a44d8ab69031c859dbd9461728",
- "sha256:271abbe28eb99fa5c70b3f272c0c66b67dab7bb11e1d29d8e616b4e0e099d29a",
- "sha256:2e1b01cba26988c811c7fb91a0bca19c9afb776cc3d228993f08d324bdd0510a",
- "sha256:3366bd6412c1e73acb1ee27d7f0c7d7dbee118ad8d98c957c8173691b2effeec",
- "sha256:3893b39a0a17d857dc3a42fdb02a26aa53a59bfce49987187bcc0261647f1f55",
- "sha256:3c7864d5ae63b787001b01b376f6315aef1a015aa9c809535235ed0ead907919",
- "sha256:42c6716adf3ec1f608b2b56e885f26dd86e80d2fc1617f51fc92d1b0b649e28e",
- "sha256:4bef0756b9e0df78e8d67a5b1e0e89b7daf41525d575f74e1f14a993c55b680d",
- "sha256:4fe081862e58b8fbef0e479aefc9a64f8f17f53074df1085d8c1fe825a6e5df4",
- "sha256:505a8d1b4ac571a51f10c4c995d5d4714f03c886604dc3c097ef5fd57bcfcf0b",
- "sha256:5c2e81b6ab9768c43f2ca1c9a4c925823aad79ae95efb351007df4b92ebce592",
- "sha256:70ff2df0c1795c5cf585a72d95bb458838b40bad5653c314b9067ba819e918f9",
- "sha256:97b5612fc5d4bbf0490a2d80bed5eab5b59112ef1640440c1a9ac824bafa6968",
- "sha256:a35f8f4a0334ed8b05db90383aecef8e49923ab430689a4360a74052f3a89cf4",
- "sha256:aafe85a8210dfa1da3c46831b7f00c3735240b7b028eeba339eaea6ffdb593fb",
- "sha256:c2e53eb253840f05278a8410628419ba7060815f86d48c9d83b6047de21c9956",
- "sha256:c3645887db3309fc87c3db740b977d403fb265ebab292f1f6a926c4661231fd5",
- "sha256:c6565cc92853af13237b2233f331efdad07339d27fe1f5f74256bfde7dc2f587",
- "sha256:cbc322c5d5615e67c2a15be631f64e6c2bab8c12505bc7c150948abdaa0bdbac",
- "sha256:df749ee982ec35ab76d37a1e637b10a92b4573e2b4e1f86a5fa8a1273c40a850",
- "sha256:e9439d7b801c86df13c6cbb4c5a7e181c058f3c119d5e119a94a5f3090a8f060",
- "sha256:f493ac4754717f25ace3614a51dd408a32b8bff3c9c0c85e9356e7e0a120a8c8",
- "sha256:f80d10bdf1a306f7063046321fd4efc7732a606acdd4e6259b8a37349079b704",
- "sha256:f83b0c91796eb42865451a20e82246011078ba067ea0744f7301e12a94ae2e1b"
- ],
- "version": "==1.28.1"
+ "sha256:013287f99c99b201aa8a5f6bc7918f616739b9be031db132d9e3b8453e95e151",
+ "sha256:0397616355760cd8282ed5ea34d51830ae4cb6613b7e5f66bed3be5d041b8b9a",
+ "sha256:074871a184483d5cd0746fd01e7d214d3ee9d36e67e32a5786b0a21f29fb8304",
+ "sha256:08a9b648dbe8852ff94b73a1c96da126834c3057ba2301d13e8c4adff334c482",
+ "sha256:0fa86ac4452602c79774783aa68979a1a7625ebb7eaabee2b6550b975b9d61e6",
+ "sha256:220c46b1fc9c9a6fcca4caac398f08f0ed43cdd63c45b7458983c4a1575ef6df",
+ "sha256:259240aab2603891553e17ad5b2655693df79e02a9b887ff605bdeb2fcd3dcc9",
+ "sha256:292635f05b6ce33f87116951d0b3d8d330bdfc5cac74f739370d60981e8c256c",
+ "sha256:344b50865914cc8e6d023457bffee9a640abb18f75d0f2bb519041961c748da9",
+ "sha256:3c2aa6d7a5e5bf73fdb1715eee777efe06dd39df03383f1cc095b2fdb34883e6",
+ "sha256:43d44548ad6ee738b941abd9f09e3b83a5c13f3e1410321023c3c148ba50e796",
+ "sha256:5043440c45c0a031f387e7f48527541c65d672005fb24cf18ef6857483557d39",
+ "sha256:58d7121f48cb94535a4cedcce32921d0d0a78563c7372a143dedeec196d1c637",
+ "sha256:5d7faa89992e015d245750ca9ac916c161bbf72777b2c60abc61da3fae41339e",
+ "sha256:5fb0923b16590bac338e92d98c7d8effb3cfad1d2e18c71bf86bde32c49cd6dd",
+ "sha256:63ee8e02d04272c3d103f44b4bce5d43ea757dd288673cea212d2f7da27967d2",
+ "sha256:64077e3a9a7cf2f59e6c76d503c8de1f18a76428f41a5b000dc53c48a0b772ff",
+ "sha256:739a72abffbd36083ff7adbb862cf1afc1e311c35834bed9c0361d8e68b063e1",
+ "sha256:75e383053dccb610590aa53eed5278db5c09bf498d3b5105ce6c776478f59352",
+ "sha256:7a11b1ebb3210f34913b8be6995936bf9ebc541a65ab69e75db5ce1fe5047e8f",
+ "sha256:8002a89ea91c0078c15d3c0daf423fd4968946be78f08545e807ea9a5ff8054a",
+ "sha256:8b42f0ac76be07a5fa31117a3388d754ad35ef05e2e34be185ca9ccbcfac2069",
+ "sha256:8ca26b489b5dc1e3d31807d329c23d6cb06fe40fbae25b0649b718947936e26a",
+ "sha256:92e54ab65e782f227e751c7555918afaba8d1229601687e89b80c2b65d2f6642",
+ "sha256:a9a7ae74cb3108e6457cf15532d4c300324b48fbcf3ef290bcd2835745f20510",
+ "sha256:ba3e43cb984399064ffaa3c0997576e46a1e268f9da05f97cd9b272f0b59ee71",
+ "sha256:baaa036540d7ace433bdf38a3fe5e41cf9f84cdf10a88bac805f678a7ca8ddcc",
+ "sha256:bf00ab06ea4f89976288f4d6224d4aa120780e30c955d4f85c3214ada29b3ddf",
+ "sha256:bf39977282a79dc1b2765cc3402c0ada571c29a491caec6ed12c0993c1ec115e",
+ "sha256:c22b19abba63562a5a200e586b5bde39d26c8ec30c92e26d209d81182371693b",
+ "sha256:c9016ab1eaf4e054099303287195f3746bd4e69f2631d040f9dca43e910a5408",
+ "sha256:d2c5e05c257859febd03f5d81b5015e1946d6bcf475c7bf63ee99cea8ab0d590",
+ "sha256:e64bddd09842ef508d72ca354319b0eb126205d951e8ac3128fe9869bd563552",
+ "sha256:e8c3264b0fd728aadf3f0324471843f65bd3b38872bdab2a477e31ffb685dd5b",
+ "sha256:ea849210e7362559f326cbe603d5b8d8bb1e556e86a7393b5a8847057de5b084",
+ "sha256:ebb2ca09fa17537e35508a29dcb05575d4d9401138a68e83d1c605d65e8a1770",
+ "sha256:ef9fce98b6fe03874c2a6576b02aec1a0df25742cd67d1d7b75a49e30aa74225",
+ "sha256:f04c59d186af3157dc8811114130aaeae92e90a65283733f41de94eed484e1f7",
+ "sha256:f5b0870b733bcb7b6bf05a02035e7aaf20f599d3802b390282d4c2309f825f1d"
+ ],
+ "version": "==1.31.0"
},
"gunicorn": {
"hashes": [
@@ -1332,65 +1387,45 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==8.2"
},
- "idna": {
+ "identify": {
"hashes": [
- "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
- "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"
+ "sha256:110ed090fec6bce1aabe3c72d9258a9de82207adeaa5a05cd75c635880312f9a",
+ "sha256:ccd88716b890ecbe10920659450a635d2d25de499b9a638525a48b48261d989b"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==2.9"
- },
- "imagecodecs": {
- "hashes": [
- "sha256:0538f7a4def1f6745b2d83d21883dcd61e82bc8faaca810e3a35e6b551b455d1",
- "sha256:22f3c39755752fe3a91a92fcf24002ca57a51efca1ab99e9919cf783f90b4026",
- "sha256:286b87ee09506c35f099585e6b5ce245fb62c2a826aac4e0497cdfdfba631cc7",
- "sha256:2bda6c7b13be73dfd202b3c23dc4b3003fdc02209835e348e4bd31ddca124d76",
- "sha256:2c130b89fcb70bab3aa57ee0671423ab0e053c6ff7ed26646bf425592fa3116d",
- "sha256:6275213bd611156fa2fd73ce81b29ca708c4344d36fe3686f567cd104ccf4d18",
- "sha256:6f63ae2592086b1abbd40b699816c054dc7aad616df2b14c2e15cd2372b77653",
- "sha256:91eb82b0167ff022a6a8dcf86e5871b635bfbe96801557e00d6b1e2a10ac25dd",
- "sha256:9742b392640c1b2d05c6aaad956bd7e3bf461c7e0f403f7b25ee464a5c949c8c",
- "sha256:9a9abc5498121f0005fb00dfbed57a062337445d32a39569e4378286b503125b",
- "sha256:adc09e5f9af6927eccc35d60ae1ec422cd9791cee4d5456d39af6903dff19477",
- "sha256:c019b19438dff31365fee3002b438992c16bc9955a036f466c600d80699cb5a2",
- "sha256:c5667d4b8e97cf10b3754f5e8159d60620cdd35052ffc298346273d42284430f",
- "sha256:c7367e01a199228b6526f05dc7fe7a85adac19f1b19e08a99edbdd2523cfcdc4",
- "sha256:cf855a00bf5cb5a7cf1d608e7588ddc535d714e5422c3095dd811829b559f237",
- "sha256:d1b0b2de7be918a8eada62c8d2339931381c86dbd43216a064e35ace5957e350",
- "sha256:e0f3cfc2fc77c19118e173dca6af0dbed4a3cef75d3296762db687fd00fb7921",
- "sha256:e8f460145258a28544d4119f58cab2daf87ac6653429ab9df7dff7d2cc30714f",
- "sha256:eedf5be2c9c65a0d92970bda98dfd7e9525c137e631e1956753bb6ce369b08f9",
- "sha256:f6722cd6a73501c508b361f485259f172898d3cf2530e6de71f3e89394a0a713",
- "sha256:f6ac9dd40e1cdb72842fb72f147e8a51a1874c8f375629524566b388e841be20",
- "sha256:fbdd0d42aa3c984377421767a892e77c40249870425aca0ba5629bdcd57d3ae4"
+ "version": "==1.4.25"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
+ "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
],
- "markers": "python_version >= '3.6'",
- "version": "==2020.2.18"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.10"
},
"imageio": {
"hashes": [
- "sha256:1e4ab29b3775bb093c7a35854a0412857145450183344678829b30e72263b001",
- "sha256:fb5fd6d3d17126bbaac9af29fe340e2c97a196eb9416d4f28c0e543744a152cf"
+ "sha256:3604d751f03002e8e0e7650aa71d8d9148144a87daf17cb1f3228e80747f2e6b",
+ "sha256:52ddbaeca2dccf53ba2d6dec5676ca7bc3b2403ef8b37f7da78b7654bb3e10f0"
],
"index": "pypi",
- "version": "==2.8.0"
+ "version": "==2.9.0"
},
"ipykernel": {
"hashes": [
- "sha256:003c9c1ab6ff87d11f531fee2b9ca59affab19676fc6b2c21da329aef6e73499",
- "sha256:2937373c356fa5b634edb175c5ea0e4b25de8008f7c194f2d49cfbd1f9c970a8"
+ "sha256:9b2652af1607986a1b231c62302d070bc0534f564c393a5d9d130db9abbbe89d",
+ "sha256:d6fbba26dba3cebd411382bc484f7bc2caa98427ae0ddb4ab37fe8bfeb5c7dd3"
],
"index": "pypi",
- "version": "==5.2.1"
+ "version": "==5.3.4"
},
"ipython": {
"hashes": [
- "sha256:5b241b84bbf0eb085d43ae9d46adf38a13b45929ca7774a740990c2c242534bb",
- "sha256:f0126781d0f959da852fb3089e170ed807388e986a8dd4e6ac44855845b0fb1c"
+ "sha256:5a8f159ca8b22b9a0a1f2a28befe5ad2b703339afb58c2ffe0d7c8d7a3af5999",
+ "sha256:b70974aaa2674b05eb86a910c02ed09956a33f2dd6c71afc60f0b128a77e7f28"
],
"index": "pypi",
- "version": "==7.14.0"
+ "version": "==7.17.0"
},
"ipython-genutils": {
"hashes": [
@@ -1431,11 +1466,11 @@
},
"jedi": {
"hashes": [
- "sha256:cd60c93b71944d628ccac47df9a60fec53150de53d42dc10a7fc4b5ba6aae798",
- "sha256:df40c97641cb943661d2db4c33c2e1ff75d491189423249e989bcea4464f3030"
+ "sha256:86ed7d9b750603e4ba582ea8edc678657fb4007894a12bcf6f4bb97892f31d20",
+ "sha256:98cc583fa0f2f8304968199b01b6b4b94f469a1f4a74c1560506ca2a211378b5"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==0.17.0"
+ "version": "==0.17.2"
},
"jinja2": {
"hashes": [
@@ -1455,11 +1490,11 @@
},
"joblib": {
"hashes": [
- "sha256:0630eea4f5664c463f23fbf5dcfc54a2bc6168902719fa8e19daf033022786c8",
- "sha256:bdb4fd9b72915ffb49fde2229ce482dd7ae79d842ed8c2b4c932441495af1403"
+ "sha256:8f52bf24c64b608bf0b2563e0e47d6fcf516abc8cfafe10cfd98ad66d94f92d6",
+ "sha256:d348c5d4ae31496b2aa060d6d9b787864dd204f9480baaa52d18850cb43e9f49"
],
"index": "pypi",
- "version": "==0.14.1"
+ "version": "==0.16.0"
},
"json-logging-py": {
"hashes": [
@@ -1486,11 +1521,11 @@
},
"jupyter-client": {
"hashes": [
- "sha256:3a32fa4d0b16d1c626b30c3002a62dfd86d6863ed39eaba3f537fade197bb756",
- "sha256:cde8e83aab3ec1c614f221ae54713a9a46d3bf28292609d2db1b439bef5a8c8e"
+ "sha256:7ad9aa91505786420d77edc5f9fb170d51050c007338ba8d196f603223fd3b3a",
+ "sha256:b360f8d4638bc577a4656e93f86298db755f915098dc763f6fc05da0c5d7a595"
],
"markers": "python_version >= '3.5'",
- "version": "==6.1.3"
+ "version": "==6.1.6"
},
"jupyter-console": {
"hashes": [
@@ -1518,22 +1553,25 @@
},
"keras-preprocessing": {
"hashes": [
- "sha256:138012da7bbc5508d59681515636c01618644322db08c1f4c6d66e63de8ddb73",
- "sha256:c0b1ebe444e46075a9079629fa0e0d0fb1d681b4a72340ca5406b574894276a5"
+ "sha256:7b82029b130ff61cc99b55f3bd27427df4838576838c5b2f65940e4fcec99a7b",
+ "sha256:add82567c50c8bc648c14195bf544a5ce7c1f76761536956c3d2978970179ef3"
],
- "version": "==1.1.1"
+ "version": "==1.1.2"
},
"kiwisolver": {
"hashes": [
"sha256:03662cbd3e6729f341a97dd2690b271e51a67a68322affab12a5b011344b973c",
"sha256:18d749f3e56c0480dccd1714230da0f328e6e4accf188dd4e6884bdd06bf02dd",
"sha256:247800260cd38160c362d211dcaf4ed0f7816afb5efe56544748b21d6ad6d17f",
+ "sha256:38d05c9ecb24eee1246391820ed7137ac42a50209c203c908154782fced90e44",
"sha256:443c2320520eda0a5b930b2725b26f6175ca4453c61f739fef7a5847bd262f74",
"sha256:4eadb361baf3069f278b055e3bb53fa189cea2fd02cb2c353b7a99ebb4477ef1",
"sha256:556da0a5f60f6486ec4969abbc1dd83cf9b5c2deadc8288508e55c0f5f87d29c",
"sha256:603162139684ee56bcd57acc74035fceed7dd8d732f38c0959c8bd157f913fec",
"sha256:60a78858580761fe611d22127868f3dc9f98871e6fdf0a15cc4203ed9ba6179b",
+ "sha256:63f55f490b958b6299e4e5bdac66ac988c3d11b7fafa522800359075d4fa56d1",
"sha256:7cc095a4661bdd8a5742aaf7c10ea9fac142d76ff1770a0f84394038126d8fc7",
+ "sha256:be046da49fbc3aa9491cc7296db7e8d27bcf0c3d5d1a40259c10471b014e4e0c",
"sha256:c31bc3c8e903d60a1ea31a754c72559398d91b5929fcb329b1c3a3d3f6e72113",
"sha256:c955791d80e464da3b471ab41eb65cf5a40c15ce9b001fdc5bbc241170de58ec",
"sha256:d069ef4b20b1e6b19f790d00097a5d5d2c50871b66d10075dab78938dc2ee2cf",
@@ -1547,10 +1585,10 @@
},
"knack": {
"hashes": [
- "sha256:4063e504db33d62e4fff00ccb0fb9563bdde6232a27764e07087db75f7de7830",
- "sha256:66d1ff609ecfa1da48f731c9258f03d5dd1da324e2cf81732c78e993afc46683"
+ "sha256:d86a669f45e875fc5e49a85ac90e57c85338be89cb281cb99a9adb87f563761d",
+ "sha256:dfc6aef6760ea9a9620577e01540617678d78cab3111a0f03e8b9f987d0f08ca"
],
- "version": "==0.7.0rc4"
+ "version": "==0.7.2"
},
"lazy-object-proxy": {
"hashes": [
@@ -1642,23 +1680,30 @@
},
"matplotlib": {
"hashes": [
- "sha256:2466d4dddeb0f5666fd1e6736cc5287a4f9f7ae6c1a9e0779deff798b28e1d35",
- "sha256:282b3fc8023c4365bad924d1bb442ddc565c2d1635f210b700722776da466ca3",
- "sha256:4bb50ee4755271a2017b070984bcb788d483a8ce3132fab68393d1555b62d4ba",
- "sha256:56d3147714da5c7ac4bc452d041e70e0e0b07c763f604110bd4e2527f320b86d",
- "sha256:7a9baefad265907c6f0b037c8c35a10cf437f7708c27415a5513cf09ac6d6ddd",
- "sha256:aae7d107dc37b4bb72dcc45f70394e6df2e5e92ac4079761aacd0e2ad1d3b1f7",
- "sha256:af14e77829c5b5d5be11858d042d6f2459878f8e296228c7ea13ec1fd308eb68",
- "sha256:c1cf735970b7cd424502719b44288b21089863aaaab099f55e0283a721aaf781",
- "sha256:ce378047902b7a05546b6485b14df77b2ff207a0054e60c10b5680132090c8ee",
- "sha256:d35891a86a4388b6965c2d527b9a9f9e657d9e110b0575ca8a24ba0d4e34b8fc",
- "sha256:e06304686209331f99640642dee08781a9d55c6e32abb45ed54f021f46ccae47",
- "sha256:e20ba7fb37d4647ac38f3c6d8672dd8b62451ee16173a0711b37ba0ce42bf37d",
- "sha256:f4412241e32d0f8d3713b68d3ca6430190a5e8a7c070f1c07d7833d8c5264398",
- "sha256:ffe2f9cdcea1086fc414e82f42271ecf1976700b8edd16ca9d376189c6d93aee"
- ],
- "index": "pypi",
- "version": "==3.2.1"
+ "sha256:09b4096748178bcc764b81587b00ab720eac24965d2bf44ecbe09dcf4e8ed253",
+ "sha256:19cf4db0272da286863a50406f6430101af129f288c421b1a7f33ddfc8d0180f",
+ "sha256:244a9088140a4c540e0a2db9c8ada5ad12520efded592a46e5bc43ff8f0fd0aa",
+ "sha256:24e8db94948019d531ce0bcd637ac24b1c8f6744ac86d2aa0eb6dbaeb1386f82",
+ "sha256:2a9d10930406748b50f60c5fa74c399a1c1080aa6ce6e3fe5f38473b02f6f06d",
+ "sha256:605e4d43b421524ad955a56535391e02866d07bce27c644e2c99e25fb59d63d1",
+ "sha256:695b4165520bdfe381d15a6db03778babb265fee7affdc43e169a881f3f329bc",
+ "sha256:6aa7ea00ad7d898704ffed46e83efd7ec985beba57f507c957979f080678b9ea",
+ "sha256:7c9adba58a67d23cc131c4189da56cb1d0f18a237c43188d831a44e4fc5df15a",
+ "sha256:7ce8f5364c74aac06abad84d8744d659bd86036e86c4ebf14c75ae4292597b46",
+ "sha256:855bb281f3cc8e23ef66064a2beb229674fdf785638091fc82a172e3e84c2780",
+ "sha256:9ccc651261b7044ffc3b1e2f9af17b1ef4c6a12fc080b5a7353ef0b53a50be28",
+ "sha256:b0786ac32983191fcd9cc0230b4ec2f8b3c25dee9beca46ca506c5d6cc5c593d",
+ "sha256:bf8d527a2eb9a5db1c9e5e405d1b1c4e66be983620c9ce80af6aae430d9a0c9c",
+ "sha256:c06ea133b44805d42f2507cb3503f6647b0c7918f1900b5063f5a8a69c63f6d2",
+ "sha256:c1f850908600efa60f81ad14eedbaf7cb17185a2c6d26586ae826ae5ce21f6e0",
+ "sha256:cef05e9a2302f96d6f0666ee70ac7715cbc12e3802d8b8eb80bacd6ab81a0a24",
+ "sha256:e3868686f3023644523df486fc224b0af4349f3cdb933b0a71f261a574d7b65f",
+ "sha256:ebb6168c9330309b1f3360d36c481d8cd621a490cf2a69c9d6625b2a76777c12",
+ "sha256:f74c39621b03cec7bc08498f140192ac26ca940ef20beac6dfad3714d2298b2a",
+ "sha256:f9753c6292d5a1fe46828feb38d1de1820e3ea109a5fea0b6ea1dca6e9d0b220"
+ ],
+ "index": "pypi",
+ "version": "==3.3.0"
},
"mccabe": {
"hashes": [
@@ -1684,10 +1729,10 @@
},
"mpld3": {
"hashes": [
- "sha256:4d455884a211bf99b37ecc760759435c7bb6a5955de47d8daf4967e301878ab7"
+ "sha256:1677a314125ff2984e2f291d595188d5ee8ca66ac21b0c2c8633961bc33a7bf8"
],
"index": "pypi",
- "version": "==0.3"
+ "version": "==0.5.1"
},
"msal": {
"hashes": [
@@ -1712,40 +1757,67 @@
},
"msrest": {
"hashes": [
- "sha256:22349c718f632e37beee0dd10f7ea41984ded136db2199a9d3c6f1f3942868e9",
- "sha256:9050fbbb95dd9e8f4008d7227e4dc5662e8b605c89e5621b0dd09ac7f04cf01d"
+ "sha256:4993023011663b4273f15432fab75cc747dfa0bca1816d8122a7d1f9fdd9288d",
+ "sha256:5f4ef9b8cc207d93978b1a58f055179686b9f30a5e28041872db97a4a1c49b96"
],
- "version": "==0.6.13"
+ "version": "==0.6.18"
},
"msrestazure": {
"hashes": [
- "sha256:0ae7f903ff81631512beef39602c4104a8fe04cb7d166f28a1ec43c0f0985749",
- "sha256:0ec9db93eeea6a6cf1240624a04f49cd8bbb26b98d84a63a8220cfda858c2a96"
+ "sha256:3de50f56147ef529b31e099a982496690468ecef33f0544cb0fa0cfe1e1de5b9",
+ "sha256:a06f0dabc9a6f5efe3b6add4bd8fb623aeadacf816b7a35b0f89107e0544d189"
],
- "version": "==0.6.3"
+ "version": "==0.6.4"
},
"multidict": {
"hashes": [
- "sha256:317f96bc0950d249e96d8d29ab556d01dd38888fbe68324f46fd834b430169f1",
- "sha256:42f56542166040b4474c0c608ed051732033cd821126493cf25b6c276df7dd35",
- "sha256:4b7df040fb5fe826d689204f9b544af469593fb3ff3a069a6ad3409f742f5928",
- "sha256:544fae9261232a97102e27a926019100a9db75bec7b37feedd74b3aa82f29969",
- "sha256:620b37c3fea181dab09267cd5a84b0f23fa043beb8bc50d8474dd9694de1fa6e",
- "sha256:6e6fef114741c4d7ca46da8449038ec8b1e880bbe68674c01ceeb1ac8a648e78",
- "sha256:7774e9f6c9af3f12f296131453f7b81dabb7ebdb948483362f5afcaac8a826f1",
- "sha256:85cb26c38c96f76b7ff38b86c9d560dea10cf3459bb5f4caf72fc1bb932c7136",
- "sha256:a326f4240123a2ac66bb163eeba99578e9d63a8654a59f4688a79198f9aa10f8",
- "sha256:ae402f43604e3b2bc41e8ea8b8526c7fa7139ed76b0d64fc48e28125925275b2",
- "sha256:aee283c49601fa4c13adc64c09c978838a7e812f85377ae130a24d7198c0331e",
- "sha256:b51249fdd2923739cd3efc95a3d6c363b67bbf779208e9f37fd5e68540d1a4d4",
- "sha256:bb519becc46275c594410c6c28a8a0adc66fe24fef154a9addea54c1adb006f5",
- "sha256:c2c37185fb0af79d5c117b8d2764f4321eeb12ba8c141a95d0aa8c2c1d0a11dd",
- "sha256:dc561313279f9d05a3d0ffa89cd15ae477528ea37aa9795c4654588a3287a9ab",
- "sha256:e439c9a10a95cb32abd708bb8be83b2134fa93790a4fb0535ca36db3dda94d20",
- "sha256:fc3b4adc2ee8474cb3cd2a155305d5f8eda0a9c91320f83e55748e1fcb68f8e3"
+ "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a",
+ "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000",
+ "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2",
+ "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507",
+ "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5",
+ "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7",
+ "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d",
+ "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463",
+ "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19",
+ "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3",
+ "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b",
+ "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c",
+ "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87",
+ "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7",
+ "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430",
+ "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255",
+ "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"
],
"markers": "python_version >= '3.5'",
- "version": "==4.7.5"
+ "version": "==4.7.6"
+ },
+ "mypy": {
+ "hashes": [
+ "sha256:2c6cde8aa3426c1682d35190b59b71f661237d74b053822ea3d748e2c9578a7c",
+ "sha256:3fdda71c067d3ddfb21da4b80e2686b71e9e5c72cca65fa216d207a358827f86",
+ "sha256:5dd13ff1f2a97f94540fd37a49e5d255950ebcdf446fb597463a40d0df3fac8b",
+ "sha256:6731603dfe0ce4352c555c6284c6db0dc935b685e9ce2e4cf220abe1e14386fd",
+ "sha256:6bb93479caa6619d21d6e7160c552c1193f6952f0668cdda2f851156e85186fc",
+ "sha256:81c7908b94239c4010e16642c9102bfc958ab14e36048fa77d0be3289dda76ea",
+ "sha256:9c7a9a7ceb2871ba4bac1cf7217a7dd9ccd44c27c2950edbc6dc08530f32ad4e",
+ "sha256:a4a2cbcfc4cbf45cd126f531dedda8485671545b43107ded25ce952aac6fb308",
+ "sha256:b7fbfabdbcc78c4f6fc4712544b9b0d6bf171069c6e0e3cb82440dd10ced3406",
+ "sha256:c05b9e4fb1d8a41d41dec8786c94f3b95d3c5f528298d769eb8e73d293abc48d",
+ "sha256:d7df6eddb6054d21ca4d3c6249cae5578cb4602951fd2b6ee2f5510ffb098707",
+ "sha256:e0b61738ab504e656d1fe4ff0c0601387a5489ca122d55390ade31f9ca0e252d",
+ "sha256:eff7d4a85e9eea55afa34888dfeaccde99e7520b51f867ac28a48492c0b1130c",
+ "sha256:f05644db6779387ccdb468cc47a44b4356fc2ffa9287135d05b70a98dc83b89a"
+ ],
+ "index": "pypi",
+ "version": "==0.782"
+ },
+ "mypy-extensions": {
+ "hashes": [
+ "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
+ "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
+ ],
+ "version": "==0.4.3"
},
"nbconvert": {
"hashes": [
@@ -1757,53 +1829,65 @@
},
"nbformat": {
"hashes": [
- "sha256:049af048ed76b95c3c44043620c17e56bc001329e07f83fec4f177f0e3d7b757",
- "sha256:276343c78a9660ab2a63c28cc33da5f7c58c092b3f3a40b6017ae2ce6689320d"
+ "sha256:54d4d6354835a936bad7e8182dcd003ca3dc0cedfee5a306090e04854343b340",
+ "sha256:ea55c9b817855e2dfcd3f66d74857342612a60b1f09653440f4a5845e6e3523f"
],
"markers": "python_version >= '3.5'",
- "version": "==5.0.6"
+ "version": "==5.0.7"
},
"networkx": {
"hashes": [
- "sha256:8311ddef63cf5c5c5e7c1d0212dd141d9a1fe3f474915281b73597ed5f1d4e3d"
+ "sha256:cdfbf698749a5014bf2ed9db4a07a5295df1d3a53bf80bf3cbd61edf9df05fa1",
+ "sha256:f8f4ff0b6f96e4f9b16af6b84622597b5334bf9cae8cf9b2e42e7985d5c95c64"
],
"index": "pypi",
- "version": "==2.3"
+ "version": "==2.4"
+ },
+ "nodeenv": {
+ "hashes": [
+ "sha256:4b0b77afa3ba9b54f4b6396e60b0c83f59eaeb2d63dc3cc7a70f7f4af96c82bc"
+ ],
+ "version": "==1.4.0"
},
"notebook": {
"hashes": [
- "sha256:3edc616c684214292994a3af05eaea4cc043f6b4247d830f3a2f209fa7639a80",
- "sha256:47a9092975c9e7965ada00b9a20f0cf637d001db60d241d479f53c0be117ad48"
+ "sha256:42391d8f3b88676e774316527599e49c11f3a7e51c41035e9e44c1b58e1398d5",
+ "sha256:4cc4e44a43a83a7c2f5e85bfdbbfe1c68bed91b857741df9e593d213a6fc2d27"
],
"markers": "python_version >= '3.5'",
- "version": "==6.0.3"
+ "version": "==6.1.1"
},
"numpy": {
"hashes": [
- "sha256:00d7b54c025601e28f468953d065b9b121ddca7fff30bed7be082d3656dd798d",
- "sha256:02ec9582808c4e48be4e93cd629c855e644882faf704bc2bd6bbf58c08a2a897",
- "sha256:0e6f72f7bb08f2f350ed4408bb7acdc0daba637e73bce9f5ea2b207039f3af88",
- "sha256:1be2e96314a66f5f1ce7764274327fd4fb9da58584eaff00b5a5221edefee7d6",
- "sha256:2466fbcf23711ebc5daa61d28ced319a6159b260a18839993d871096d66b93f7",
- "sha256:2b573fcf6f9863ce746e4ad00ac18a948978bb3781cffa4305134d31801f3e26",
- "sha256:3f0dae97e1126f529ebb66f3c63514a0f72a177b90d56e4bce8a0b5def34627a",
- "sha256:50fb72bcbc2cf11e066579cb53c4ca8ac0227abb512b6cbc1faa02d1595a2a5d",
- "sha256:57aea170fb23b1fd54fa537359d90d383d9bf5937ee54ae8045a723caa5e0961",
- "sha256:709c2999b6bd36cdaf85cf888d8512da7433529f14a3689d6e37ab5242e7add5",
- "sha256:7d59f21e43bbfd9a10953a7e26b35b6849d888fc5a331fa84a2d9c37bd9fe2a2",
- "sha256:904b513ab8fbcbdb062bed1ce2f794ab20208a1b01ce9bd90776c6c7e7257032",
- "sha256:96dd36f5cdde152fd6977d1bbc0f0561bccffecfde63cd397c8e6033eb66baba",
- "sha256:9933b81fecbe935e6a7dc89cbd2b99fea1bf362f2790daf9422a7bb1dc3c3085",
- "sha256:bbcc85aaf4cd84ba057decaead058f43191cc0e30d6bc5d44fe336dc3d3f4509",
- "sha256:dccd380d8e025c867ddcb2f84b439722cf1f23f3a319381eac45fd077dee7170",
- "sha256:e22cd0f72fc931d6abc69dc7764484ee20c6a60b0d0fee9ce0426029b1c1bdae",
- "sha256:ed722aefb0ebffd10b32e67f48e8ac4c5c4cf5d3a785024fdf0e9eb17529cd9d",
- "sha256:efb7ac5572c9a57159cf92c508aad9f856f1cb8e8302d7fdb99061dbe52d712c",
- "sha256:efdba339fffb0e80fcc19524e4fdbda2e2b5772ea46720c44eaac28096d60720",
- "sha256:f22273dd6a403ed870207b853a856ff6327d5cbce7a835dfa0645b3fc00273ec"
- ],
- "index": "pypi",
- "version": "==1.18.4"
+ "sha256:082f8d4dd69b6b688f64f509b91d482362124986d98dc7dc5f5e9f9b9c3bb983",
+ "sha256:1bc0145999e8cb8aed9d4e65dd8b139adf1919e521177f198529687dbf613065",
+ "sha256:309cbcfaa103fc9a33ec16d2d62569d541b79f828c382556ff072442226d1968",
+ "sha256:3673c8b2b29077f1b7b3a848794f8e11f401ba0b71c49fbd26fb40b71788b132",
+ "sha256:480fdd4dbda4dd6b638d3863da3be82873bba6d32d1fc12ea1b8486ac7b8d129",
+ "sha256:56ef7f56470c24bb67fb43dae442e946a6ce172f97c69f8d067ff8550cf782ff",
+ "sha256:5a936fd51049541d86ccdeef2833cc89a18e4d3808fe58a8abeb802665c5af93",
+ "sha256:5b6885c12784a27e957294b60f97e8b5b4174c7504665333c5e94fbf41ae5d6a",
+ "sha256:667c07063940e934287993366ad5f56766bc009017b4a0fe91dbd07960d0aba7",
+ "sha256:7ed448ff4eaffeb01094959b19cbaf998ecdee9ef9932381420d514e446601cd",
+ "sha256:8343bf67c72e09cfabfab55ad4a43ce3f6bf6e6ced7acf70f45ded9ebb425055",
+ "sha256:92feb989b47f83ebef246adabc7ff3b9a59ac30601c3f6819f8913458610bdcc",
+ "sha256:935c27ae2760c21cd7354402546f6be21d3d0c806fffe967f745d5f2de5005a7",
+ "sha256:aaf42a04b472d12515debc621c31cf16c215e332242e7a9f56403d814c744624",
+ "sha256:b12e639378c741add21fbffd16ba5ad25c0a1a17cf2b6fe4288feeb65144f35b",
+ "sha256:b1cca51512299841bf69add3b75361779962f9cee7d9ee3bb446d5982e925b69",
+ "sha256:b8456987b637232602ceb4d663cb34106f7eb780e247d51a260b84760fd8f491",
+ "sha256:b9792b0ac0130b277536ab8944e7b754c69560dac0415dd4b2dbd16b902c8954",
+ "sha256:c9591886fc9cbe5532d5df85cb8e0cc3b44ba8ce4367bd4cf1b93dc19713da72",
+ "sha256:cf1347450c0b7644ea142712619533553f02ef23f92f781312f6a3553d031fc7",
+ "sha256:de8b4a9b56255797cbddb93281ed92acbc510fb7b15df3f01bd28f46ebc4edae",
+ "sha256:e1b1dc0372f530f26a03578ac75d5e51b3868b9b76cd2facba4c9ee0eb252ab1",
+ "sha256:e45f8e981a0ab47103181773cc0a54e650b2aef8c7b6cd07405d0fa8d869444a",
+ "sha256:e4f6d3c53911a9d103d8ec9518190e52a8b945bab021745af4939cfc7c0d4a9e",
+ "sha256:ed8a311493cf5480a2ebc597d1e177231984c818a86875126cfd004241a73c3e",
+ "sha256:ef71a1d4fd4858596ae80ad1ec76404ad29701f8ca7cdcebc50300178db14dfc"
+ ],
+ "index": "pypi",
+ "version": "==1.19.1"
},
"oauthlib": {
"hashes": [
@@ -1815,97 +1899,96 @@
},
"opencv-python": {
"hashes": [
- "sha256:068928b9907b3d3acd53b129062557d6b0b8b324bfade77f028dbe4dfe482bf2",
- "sha256:0e7c91718351449877c2d4141abd64eee1f9c8701bcfaf4e8627bd023e303368",
- "sha256:1ab92d807427641ec45d28d5907426aa06b4ffd19c5b794729c74d91cd95090e",
- "sha256:31d634dea1b47c231b88d384f90605c598214d0c596443c9bb808e11761829f5",
- "sha256:5fdfc0bed37315f27d30ae5ae9bad47ec0a0a28c323739d39c8177b7e0929238",
- "sha256:6fa8fac14dd5af4819d475f74af12d65fbbfa391d3110c3a972934a5e6507c24",
- "sha256:78cc89ebc808886eb190626ee71ab65e47f374121975f86e4d5f7c0e3ce6bed9",
- "sha256:7c7ba11720d01cb572b4b6945d115cb103462c0a28996b44d4e540d06e6a90fd",
- "sha256:a37ee82f1b8ed4b4645619c504311e71ce845b78f40055e78d71add5fab7da82",
- "sha256:aa3ca1f54054e1c6439fdf1edafa2a2b940a9eaac04a7b422a1cba9b2d7b9690",
- "sha256:b9de3dd956574662712da8e285f0f54327959a4e95b96a2847d3c3f5ee7b96e2",
- "sha256:c0087b428cef9a32d977390656d91b02245e0e91f909870492df7e39202645dd",
- "sha256:d87e506ab205799727f0efa34b3888949bf029a3ada5eb000ff632606370ca6e",
- "sha256:d8a55585631f9c9eca4b1a996e9732ae023169cf2f46f69e4518d67d96198226",
- "sha256:dcb8da8c5ebaa6360c8555547a4c7beb6cd983dd95ba895bb78b86cc8cf3de2b",
- "sha256:e2206bb8c17c0f212f1f356d82d72dd090ff4651994034416da9bf0c29732825",
- "sha256:e3c57d6579e5bf85f564d6d48d8ee89868b92879a9232b9975d072c346625e92",
- "sha256:ef89cbf332b9a735d8a82e9ff79cc743eeeb775ad1cd7100bc2aa2429b496f07",
- "sha256:f45c1c3cdda1857bedd4dfe0bbd49c9419af0cc57f33490341edeae97d18f037",
- "sha256:fb3c855347310788e4286b867997be354c55535597966ed5dac876d9166013a4"
- ],
- "index": "pypi",
- "version": "==4.2.0.34"
+ "sha256:156e2954d5b38b676e8a24d66703cf15f252e24ec49db7e842a8b5eed46074ba",
+ "sha256:1bf486680a16d739f7852a62865b72eb7692df584694815774ba97b471b8bc3f",
+ "sha256:1ea08f22246ccd33174d59edfa3f13930bf2c28096568242090bd9d8770fb8a8",
+ "sha256:210ab40c8c9dadc7dc9ed7beebe2e0a2415a744f8d6857762a80c8e0fcc477c8",
+ "sha256:2ec6502bfac01b27ac06daf7bc9f7a4f482a6a0d8e1b30e15c411d478454a19f",
+ "sha256:2fe704e35808cf6b17b793e89fd00e9ef7779f85f274666a4e092671aedd09c0",
+ "sha256:4b93b5f8df187e4dba9fb25c46fa8cf342c257de144f7c86d75c06416566a199",
+ "sha256:55e1d7a2d11c40ea5b53aabe5c4122038803c7d492505c8f93af077aa7fe2ce1",
+ "sha256:677f61332436e22f83a1e4e6f6863a760734fbc8029ba6a8ef0af4554cde6f93",
+ "sha256:76ddc6daf8607eda1d866395dcf98526ef96f3e616d8c37ccc7629f9aaf6d4d4",
+ "sha256:c4f1e9d963c8f370284afa87fcf521cc8439a610a500bf8ede27fd64dd9050bd",
+ "sha256:c93b1198c85175a9fa9a9839c4da55c7ab9c5f57256f2e4211cd6c91d7d422e8",
+ "sha256:d765c44827778cbe6bc8f272cd61514e8509b93fd24dd3324cd4abddf2026b11",
+ "sha256:eb709245e56f6693d297f8818ff8e6c017fa80fdb5a923c64be623a678c7150e",
+ "sha256:ef4ac758a4e2caee80ef9c86b83a279d6f132c9e7ae77957cf74013928814e05",
+ "sha256:f67c1d92ff96c6c106f786b7ef9b9ab448fa03ef28cb7bb6f0f7b857b65bc158",
+ "sha256:f6fa2834d85c78865ca6e3de563916086cb8c83c3f2ef80924fcd07005f05df9",
+ "sha256:fa1a6d149a1a5e0bc54c737a59fe38d75384a092ae5e35f9b876fbb621f755c6",
+ "sha256:fd457deedcf153dd6805a2b4d891ac2a0969566d3755fbf48a3ffb53978c9ed1"
+ ],
+ "index": "pypi",
+ "version": "==4.3.0.36"
},
"opt-einsum": {
"hashes": [
- "sha256:83b76a98d18ae6a5cc7a0d88955a7f74881f0e567a0f4c949d24c942753eb998",
- "sha256:96f819d46da2f937eaf326336a114aaeccbcbdb9de460d42e8b5f480a69adca7"
+ "sha256:2455e59e3947d3c275477df7f5205b30635e266fe6dc300e3d9f9646bfcea147",
+ "sha256:59f6475f77bbc37dcf7cd748519c0ec60722e91e63ca114e68821c0c54a46549"
],
"markers": "python_version >= '3.5'",
- "version": "==3.2.1"
+ "version": "==3.3.0"
},
"osmium": {
"hashes": [
- "sha256:0d9cfeaad95c69c5d19036f2065514cf09705ebbcf2b941c05d2a39ebed82acd",
- "sha256:1229bf453a20454ac0cd64f6fd72ba05560f6e1967d0c744fad28ae1f0789457",
- "sha256:1b5af19fa354c8ab3425075db87d6a022aca2d83344b07acac5ab8be1a03c8d6",
- "sha256:1eec17f65688aa8c093c626102dae49c901227e1043ec4894b1e1b718c8cc78c",
- "sha256:2133fff59b7c8964f4d7cce44505c994d3a72203c056b2722ddbdce1c101444b",
- "sha256:2c42280676c05267a264481c9c691cfb2cbb64c1ac40b38ec834568fae205aa6",
- "sha256:2dade90a89a4afc2aba89fb3a6e160f660c577bc98f5765c6a4a7f8d7451019b",
- "sha256:38feb096933ad93891b7268f1b0894eac0fdfb91bec638153ce43a74c05fe150",
- "sha256:4744d5c36f566a617fdb5fa4955f124926c86ee61acf18c1d870ced71fde3f2c",
- "sha256:50a6395a233a17af643c48a0a92bf6173a1eb84243dcaa9ed07f373a5e3bb941",
- "sha256:512c3313cfcc1ccbaff0c7a5f618ff24d6dd7de9aceaa8c21c9cada232209708",
- "sha256:516c71dcf343003f7910c54d902042dba228b3c55ae5875220d94216861b4fbe",
- "sha256:65da41c65b40f3a86c34a24848fe015d94d6e2f202baaabf1aca345b166b8239",
- "sha256:7fbcad84cbec60359110f517650a99bc79fc966daf509ecb69e070fa7ca223e7",
- "sha256:8648692409fb88f6d545890e4fda6538ed74c366d9b722f5c54d9a7f154468f8",
- "sha256:9cde2311893a3727472538b3029196ceee1a2c21965c9edfb15e5fc1c1b8d18d",
- "sha256:a172ea24e69266be52f06bb8dc2c8670e36e2fd4e442e4227ec3de8110ed0152",
- "sha256:a533f109ed17f298d094d50fc99bd16635163fc3efda9f6fa39bb6b387100f7b",
- "sha256:aa65fcdb366a01aacdb049e12f53e73326372f2fbe8832af1e350652e6b20c07",
- "sha256:aad4b3887e0744a1b8457b368df6319c013ee4e707e5b6bb799771b20328faa7",
- "sha256:ab250ce243fd5507c36d3f93b8e01cef5cae42cddb80e2353b3fd1ea7f3d7478",
- "sha256:b792ff0b1569507afec1f4beced42d3402bd3a082dc525d9f27289f1f329c3ae",
- "sha256:bafbd0d57f4376cbab9c2901490fc021df2078cb8c89b8ffe250798e43d8bc82",
- "sha256:cd4b8f484b99f11cfdf9c0da970282534e0cafcc6a3107879f06ebb41b9f64f9"
- ],
- "index": "pypi",
- "version": "==3.0.0"
+ "sha256:04e2f3380525c9b100d7c9350e107ae0d75c378c4c36d17cc4999c5952b33960",
+ "sha256:0a5e9cccd9c376ab31fe79cdb1efcd1eb8175e7ff74a1f7ac218bd084d1a819d",
+ "sha256:32e0b94c9a6f24c3f86787a5e23d7289c00467a19d13ff2552feb2810d8b76c3",
+ "sha256:396557cc44f9655419060fb56623822b64af3f835df1f35ca0bb5aad2b5f33fe",
+ "sha256:44cd17932ef17c1c749ff5585a76e68b4615bfbe94828b7765bdebb39dfb2d85",
+ "sha256:6909a93173acd4111cc179bd7317e8a4e656c3b7b1a9041c5a5a8fcd01dbc3b5",
+ "sha256:7638dd47f667ab2f18e0092036851e4ead4a47fb5840ff138e20c02bd47d14d7",
+ "sha256:7c3782400d001229302bdffd6f410c460b270aef29a4a58c45fd479c897825b6",
+ "sha256:8451c8ebdb39b7f3d5bc038c0230f592d4dffa50ec6baef64ee8baa72e814e8a",
+ "sha256:84a7259ab1c2a37b399cfd53b82c402daf8df611ce9223dc443ccf3142b97223",
+ "sha256:8bf205bed661aa0ab7cb39f00981ced6b1f46d923c5aec246e89616b45f64dd2",
+ "sha256:97de71233b4741992008ca49e77c0a92999e9077cec9d6511759ba5d55faedde",
+ "sha256:a4a2a7c55696ad32f809dfb48f0eca1acffc6d447063d2062aaca6d6f9a26946",
+ "sha256:a60445b2122e159d7775d57f4958191ea5a32395b289c91156841ef04bdc2182",
+ "sha256:a8f4ecebe1d536ab7cdd02fa9f82ff745dd4aa8ed478ccf588f586b4c4af38a9",
+ "sha256:c3526f17eeb58eda0525888542ae14586745b0faaaf00dca2ccf2d376b75899f",
+ "sha256:c85c2bc37b118b93dc8eb6c141bf415eff34c35084613be29ced3b969b49c7f6",
+ "sha256:ce18818b7260113fcedb54e3167da0e9a07723a92f23a594318086d8c09645df",
+ "sha256:cf78640c5cd9b8e76ee37b5c0522c5130469d3db26ffdfd54e8fb751477787f5",
+ "sha256:d5da39de1c00d0c0ef8771df29424abb8bdc3fe093641c1df7448f0a22266f28",
+ "sha256:e25a2f8f495ff7d96c1c3a4c636ea5aa5176b58d5323350f913b30a6a1b67159",
+ "sha256:ede6fed48da8512415a4a895c2ded2777dacddfacc1b342f7938aa4271c97bd1",
+ "sha256:f247a74c6a02016c7f3749f5fc6fad3abaa5c7874ae2be9516ef1649dc276792",
+ "sha256:fe43969f2fb021051c2c202c28bd42bd7453f3f41d5d2499126b16437bb52f63"
+ ],
+ "index": "pypi",
+ "version": "==3.0.1"
},
"packaging": {
"hashes": [
- "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3",
- "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"
+ "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8",
+ "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==20.3"
+ "version": "==20.4"
},
"pandas": {
"hashes": [
- "sha256:07c1b58936b80eafdfe694ce964ac21567b80a48d972879a359b3ebb2ea76835",
- "sha256:0ebe327fb088df4d06145227a4aa0998e4f80a9e6aed4b61c1f303bdfdf7c722",
- "sha256:11c7cb654cd3a0e9c54d81761b5920cdc86b373510d829461d8f2ed6d5905266",
- "sha256:12f492dd840e9db1688126216706aa2d1fcd3f4df68a195f9479272d50054645",
- "sha256:167a1315367cea6ec6a5e11e791d9604f8e03f95b57ad227409de35cf850c9c5",
- "sha256:1a7c56f1df8d5ad8571fa251b864231f26b47b59cbe41aa5c0983d17dbb7a8e4",
- "sha256:1fa4bae1a6784aa550a1c9e168422798104a85bf9c77a1063ea77ee6f8452e3a",
- "sha256:32f42e322fb903d0e189a4c10b75ba70d90958cc4f66a1781ed027f1a1d14586",
- "sha256:387dc7b3c0424327fe3218f81e05fc27832772a5dffbed385013161be58df90b",
- "sha256:6597df07ea361231e60c00692d8a8099b519ed741c04e65821e632bc9ccb924c",
- "sha256:743bba36e99d4440403beb45a6f4f3a667c090c00394c176092b0b910666189b",
- "sha256:858a0d890d957ae62338624e4aeaf1de436dba2c2c0772570a686eaca8b4fc85",
- "sha256:863c3e4b7ae550749a0bb77fa22e601a36df9d2905afef34a6965bed092ba9e5",
- "sha256:a210c91a02ec5ff05617a298ad6f137b9f6f5771bf31f2d6b6367d7f71486639",
- "sha256:ca84a44cf727f211752e91eab2d1c6c1ab0f0540d5636a8382a3af428542826e",
- "sha256:d234bcf669e8b4d6cbcd99e3ce7a8918414520aeb113e2a81aeb02d0a533d7f7"
+ "sha256:0210f8fe19c2667a3817adb6de2c4fd92b1b78e1975ca60c0efa908e0985cbdb",
+ "sha256:0227e3a6e3a22c0e283a5041f1e3064d78fbde811217668bb966ed05386d8a7e",
+ "sha256:0bc440493cf9dc5b36d5d46bbd5508f6547ba68b02a28234cd8e81fdce42744d",
+ "sha256:16504f915f1ae424052f1e9b7cd2d01786f098fbb00fa4e0f69d42b22952d798",
+ "sha256:182a5aeae319df391c3df4740bb17d5300dcd78034b17732c12e62e6dd79e4a4",
+ "sha256:35db623487f00d9392d8af44a24516d6cb9f274afaf73cfcfe180b9c54e007d2",
+ "sha256:40ec0a7f611a3d00d3c666c4cceb9aa3f5bf9fbd81392948a93663064f527203",
+ "sha256:47a03bfef80d6812c91ed6fae43f04f2fa80a4e1b82b35aa4d9002e39529e0b8",
+ "sha256:4b21d46728f8a6be537716035b445e7ef3a75dbd30bd31aa1b251323219d853e",
+ "sha256:4d1a806252001c5db7caecbe1a26e49a6c23421d85a700960f6ba093112f54a1",
+ "sha256:60e20a4ab4d4fec253557d0fc9a4e4095c37b664f78c72af24860c8adcd07088",
+ "sha256:9f61cca5262840ff46ef857d4f5f65679b82188709d0e5e086a9123791f721c8",
+ "sha256:a15835c8409d5edc50b4af93be3377b5dd3eb53517e7f785060df1f06f6da0e2",
+ "sha256:b39508562ad0bb3f384b0db24da7d68a2608b9ddc85b1d931ccaaa92d5e45273",
+ "sha256:ed60848caadeacecefd0b1de81b91beff23960032cded0ac1449242b506a3b3f",
+ "sha256:fc714895b6de6803ac9f661abb316853d0cd657f5d23985222255ad76ccedc25"
],
"markers": "python_version >= '3.6.1'",
- "version": "==1.0.3"
+ "version": "==1.1.0"
},
"pandocfilters": {
"hashes": [
@@ -1913,6 +1996,14 @@
],
"version": "==1.4.2"
},
+ "parameterized": {
+ "hashes": [
+ "sha256:190f8cc7230eee0b56b30d7f074fd4d165f7c45e6077582d0813c8557e738490",
+ "sha256:59ab908e31c01505a987a2be78854e19cb1630c047bbab7848169c371d614d56"
+ ],
+ "index": "pypi",
+ "version": "==0.7.4"
+ },
"paramiko": {
"hashes": [
"sha256:920492895db8013f6cc0179293147f830b8c7b21fdfc839b6bad760c27459d9f",
@@ -1923,11 +2014,11 @@
},
"parso": {
"hashes": [
- "sha256:158c140fc04112dc45bca311633ae5033c2c2a7b732fa33d0955bad8152a8dd0",
- "sha256:908e9fae2144a076d72ae4e25539143d40b8e3eafbaeae03c1bfe226f4cdf12c"
+ "sha256:97218d9159b2520ff45eb78028ba8b50d2bc61dcc062a9682666f2dc4bd331ea",
+ "sha256:caba44724b994a8a5e086460bb212abc5a8bc46951bf4a9a1210745953622eb9"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==0.7.0"
+ "version": "==0.7.1"
},
"pexpect": {
"hashes": [
@@ -1946,32 +2037,35 @@
},
"pillow": {
"hashes": [
- "sha256:04766c4930c174b46fd72d450674612ab44cca977ebbcc2dde722c6933290107",
- "sha256:0e2a3bceb0fd4e0cb17192ae506d5f082b309ffe5fc370a5667959c9b2f85fa3",
- "sha256:0f01e63c34f0e1e2580cc0b24e86a5ccbbfa8830909a52ee17624c4193224cd9",
- "sha256:12e4bad6bddd8546a2f9771485c7e3d2b546b458ae8ff79621214119ac244523",
- "sha256:1f694e28c169655c50bb89a3fa07f3b854d71eb47f50783621de813979ba87f3",
- "sha256:3d25dd8d688f7318dca6d8cd4f962a360ee40346c15893ae3b95c061cdbc4079",
- "sha256:4b02b9c27fad2054932e89f39703646d0c543f21d3cc5b8e05434215121c28cd",
- "sha256:70e3e0d99a0dcda66283a185f80697a9b08806963c6149c8e6c5f452b2aa59c0",
- "sha256:9744350687459234867cbebfe9df8f35ef9e1538f3e729adbd8fde0761adb705",
- "sha256:a0b49960110bc6ff5fead46013bcb8825d101026d466f3a4de3476defe0fb0dd",
- "sha256:ae2b270f9a0b8822b98655cb3a59cdb1bd54a34807c6c56b76dd2e786c3b7db3",
- "sha256:b37bb3bd35edf53125b0ff257822afa6962649995cbdfde2791ddb62b239f891",
- "sha256:b532bcc2f008e96fd9241177ec580829dee817b090532f43e54074ecffdcd97f",
- "sha256:b67a6c47ed963c709ed24566daa3f95a18f07d3831334da570c71da53d97d088",
- "sha256:b943e71c2065ade6fef223358e56c167fc6ce31c50bc7a02dd5c17ee4338e8ac",
- "sha256:ccc9ad2460eb5bee5642eaf75a0438d7f8887d484490d5117b98edd7f33118b7",
- "sha256:d23e2aa9b969cf9c26edfb4b56307792b8b374202810bd949effd1c6e11ebd6d",
- "sha256:eaa83729eab9c60884f362ada982d3a06beaa6cc8b084cf9f76cae7739481dfa",
- "sha256:ee94fce8d003ac9fd206496f2707efe9eadcb278d94c271f129ab36aa7181344",
- "sha256:f455efb7a98557412dc6f8e463c1faf1f1911ec2432059fa3e582b6000fc90e2",
- "sha256:f46e0e024346e1474083c729d50de909974237c72daca05393ee32389dabe457",
- "sha256:f54be399340aa602066adb63a86a6a5d4f395adfdd9da2b9a0162ea808c7b276",
- "sha256:f784aad988f12c80aacfa5b381ec21fd3f38f851720f652b9f33facc5101cf4d"
- ],
- "index": "pypi",
- "version": "==7.1.2"
+ "sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f",
+ "sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8",
+ "sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad",
+ "sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f",
+ "sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae",
+ "sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d",
+ "sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5",
+ "sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b",
+ "sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8",
+ "sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233",
+ "sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6",
+ "sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727",
+ "sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f",
+ "sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38",
+ "sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4",
+ "sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626",
+ "sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d",
+ "sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6",
+ "sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63",
+ "sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f",
+ "sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41",
+ "sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1",
+ "sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d",
+ "sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9",
+ "sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a",
+ "sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce"
+ ],
+ "index": "pypi",
+ "version": "==7.2.0"
},
"pkginfo": {
"hashes": [
@@ -1980,33 +2074,34 @@
],
"version": "==1.5.0.1"
},
- "pooch": {
+ "portalocker": {
"hashes": [
- "sha256:453448b430ab4821178a5a5271bffece8163d4ca4e282a470f5700d55d26c697",
- "sha256:b29687cd3a553d96d73c1fcbaa7551ff5b02a5503bdcd0fa1b1c96d18049d2c3"
+ "sha256:34cb36c618d88bcd9079beb36dcdc1848a3e3d92ac4eac59055bdeafc39f9d4a",
+ "sha256:6d6f5de5a3e68c4dd65a98ec1babb26d28ccc5e770e07b672d65d5a35e4b2d8a"
],
- "markers": "python_version >= '3.5'",
- "version": "==1.1.0"
+ "version": "==1.7.1"
},
- "portalocker": {
+ "pprofile": {
"hashes": [
- "sha256:091364838ed6fbb68ea291c28982d1e56125c0d9e3fad5a4ac001db54dd862dc",
- "sha256:874d6063c6ceb185fe4771da41b01872d2c56d292db746698f8ad7bf1833c905"
+ "sha256:c2787af57c44c48e6c7e518d522fd0f93983892bfaae74ed340da02ed500ec5f"
],
- "version": "==1.7.0"
+ "index": "pypi",
+ "version": "==2.0.5"
},
- "pprofile": {
+ "pre-commit": {
"hashes": [
- "sha256:2036522d201188641ab6766b3fea105ddeb72d3b752a7d6da695be7e7ba21656"
+ "sha256:1657663fdd63a321a4a739915d7d03baedd555b25054449090f97bb0cb30a915",
+ "sha256:e8b1315c585052e729ab7e99dcca5698266bedce9067d21dc909c23e3ceed626"
],
"index": "pypi",
- "version": "==2.0.4"
+ "version": "==2.6.0"
},
"prometheus-client": {
"hashes": [
- "sha256:71cd24a2b3eb335cb800c7159f423df1bd4dcd5171b234be15e3f31ec9f622da"
+ "sha256:983c7ac4b47478720db338f1491ef67a100b474e3bc7dafcbaefb7d0b8f9b01c",
+ "sha256:c6e6b706833a6bd1fd51711299edee907857be10ece535126a158f911ee80915"
],
- "version": "==0.7.1"
+ "version": "==0.8.0"
},
"prompt-toolkit": {
"hashes": [
@@ -2018,27 +2113,26 @@
},
"protobuf": {
"hashes": [
- "sha256:0bae429443cc4748be2aadfdaf9633297cfaeb24a9a02d0ab15849175ce90fab",
- "sha256:24e3b6ad259544d717902777b33966a1a069208c885576254c112663e6a5bb0f",
- "sha256:2affcaba328c4662f3bc3c0e9576ea107906b2c2b6422344cdad961734ff6b93",
- "sha256:310a7aca6e7f257510d0c750364774034272538d51796ca31d42c3925d12a52a",
- "sha256:52e586072612c1eec18e1174f8e3bb19d08f075fc2e3f91d3b16c919078469d0",
- "sha256:73152776dc75f335c476d11d52ec6f0f6925774802cd48d6189f4d5d7fe753f4",
- "sha256:7774bbbaac81d3ba86de646c39f154afc8156717972bf0450c9dbfa1dc8dbea2",
- "sha256:82d7ac987715d8d1eb4068bf997f3053468e0ce0287e2729c30601feb6602fee",
- "sha256:8eb9c93798b904f141d9de36a0ba9f9b73cc382869e67c9e642c0aba53b0fc07",
- "sha256:adf0e4d57b33881d0c63bb11e7f9038f98ee0c3e334c221f0858f826e8fb0151",
- "sha256:c40973a0aee65422d8cb4e7d7cbded95dfeee0199caab54d5ab25b63bce8135a",
- "sha256:c77c974d1dadf246d789f6dad1c24426137c9091e930dbf50e0a29c1fcf00b1f",
- "sha256:dd9aa4401c36785ea1b6fff0552c674bdd1b641319cb07ed1fe2392388e9b0d7",
- "sha256:e11df1ac6905e81b815ab6fd518e79be0a58b5dc427a2cf7208980f30694b956",
- "sha256:e2f8a75261c26b2f5f3442b0525d50fd79a71aeca04b5ec270fc123536188306",
- "sha256:e512b7f3a4dd780f59f1bf22c302740e27b10b5c97e858a6061772668cd6f961",
- "sha256:ef2c2e56aaf9ee914d3dccc3408d42661aaf7d9bb78eaa8f17b2e6282f214481",
- "sha256:fac513a9dc2a74b99abd2e17109b53945e364649ca03d9f7a0b96aa8d1807d0a",
- "sha256:fdfb6ad138dbbf92b5dbea3576d7c8ba7463173f7d2cb0ca1bd336ec88ddbd80"
- ],
- "version": "==3.11.3"
+ "sha256:0b00429b87821f1e6f3d641327864e6f271763ae61799f7540bc58a352825fe2",
+ "sha256:2636c689a6a2441da9a2ef922a21f9b8bfd5dfe676abd77d788db4b36ea86bee",
+ "sha256:2becd0e238ae34caf96fa7365b87f65b88aebcf7864dfe5ab461c5005f4256d9",
+ "sha256:2db6940c1914fa3fbfabc0e7c8193d9e18b01dbb4650acac249b113be3ba8d9e",
+ "sha256:32f0bcdf85e0040f36b4f548c71177027f2a618cab00ba235197fa9e230b7289",
+ "sha256:3d59825cba9447e8f4fcacc1f3c892cafd28b964e152629b3f420a2fb5918b5a",
+ "sha256:4794a7748ee645d2ae305f3f4f0abd459e789c973b5bc338008960f83e0c554b",
+ "sha256:50b7bb2124f6a1fb0ddc6a44428ae3a21e619ad2cdf08130ac6c00534998ef07",
+ "sha256:6009f3ebe761fad319b52199a49f1efa7a3729302947a78a3f5ea8e7e89e3ac2",
+ "sha256:a7b6cf201e67132ca99b8a6c4812fab541fdce1ceb54bb6f66bc336ab7259138",
+ "sha256:b6842284bb15f1b19c50c5fd496f1e2a4cfefdbdfa5d25c02620cb82793295a7",
+ "sha256:c0c8d7c8f07eacd9e98a907941b56e57883cf83de069cfaeaa7e02c582f72ddb",
+ "sha256:c99e5aea75b6f2b29c8d8da5bdc5f5ed8d9a5b4f15115c8316a3f0a850f94656",
+ "sha256:e2bd5c98952db3f1bb1af2e81b6a208909d3b8a2d32f7525c5cc10a6338b6593",
+ "sha256:e77ca4e1403b363a88bde9e31c11d093565e925e1685f40b29385a52f2320794",
+ "sha256:ef991cbe34d7bb935ba6349406a210d3558b9379c21621c6ed7b99112af7350e",
+ "sha256:f10ba89f9cd508dc00e469918552925ef7cba38d101ca47af1e78f2f9982c6b3",
+ "sha256:f1796e0eb911bf5b08e76b753953effbeb6bc42c95c16597177f627eaa52c375"
+ ],
+ "version": "==3.12.4"
},
"ptyprocess": {
"hashes": [
@@ -2050,8 +2144,19 @@
},
"pyasn1": {
"hashes": [
+ "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359",
+ "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576",
+ "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf",
+ "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7",
"sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d",
- "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"
+ "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00",
+ "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8",
+ "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86",
+ "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12",
+ "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776",
+ "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba",
+ "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2",
+ "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"
],
"version": "==0.4.8"
},
@@ -2073,12 +2178,6 @@
],
"version": "==0.2.8"
},
- "pycocotools": {
- "git": "https://github.com/cocodataset/cocoapi.git",
- "ref": "8c9bcc3cf640524c4c20a9c40e89cb6a2f2fa0e9",
- "subdirectory": "PythonAPI",
- "version": "==2.0"
- },
"pycparser": {
"hashes": [
"sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
@@ -2112,44 +2211,43 @@
},
"pygame": {
"hashes": [
- "sha256:026e835dc69ab50db3f62e01884dceeee25283c04f5dbe992f059e24c11e29b3",
- "sha256:07d9f21e2aee6679bcff760b93d336ca0981000a5bb6e665708ea9f08e9c06f6",
- "sha256:134be66f54e1d588d3198f308afed3d495e5e9c1b1c36ffe71efc0afd2057eaf",
- "sha256:1b153b52e1d46f1e779ef773707d23f03d23f014819ad3a822c2e357adbeed78",
- "sha256:33795983f9fdce22b6e934f62d813364dbbd8846de25500fb9328f2a0ea619f9",
- "sha256:33b50c90559b944b466f1cd0181a3019f80f50783fe58f43369b078c0c7172ef",
- "sha256:3438463f73cc3d413b8c30daf194b5471b565cd74e4cfe0379562af534d44f22",
- "sha256:34b03b5c411b60e1dca096f0237a59521b5cab0d32b388c5b3a00c1d371a5266",
- "sha256:46211c0e87486c70a272246087bb8c221f546f0a5d258e7e722372de3bbfb887",
- "sha256:545da86be8ed0f9af19e636ecf1c6ed2d2851d64abed7f1a64e517abb2f3058b",
- "sha256:54b55f9f2fcf80aaf8c8ce2fd465e1b5cac948ccbd5a1d74561e63a9d9abd5f5",
- "sha256:56fb61d0dcd8dfe9d35f402ee417bc4bc96ea41a84525efb3cda5403f9e13bda",
- "sha256:587a5d52ba71ea16b299dce672d8d986364c9a4b0640fef49351839fa14a5950",
- "sha256:7183302b00706ed6a886fac9775fb7f44e7a96b60aab75c73473a763a19f62b8",
- "sha256:72238e9681713e68576483c8e8d7ea63c1b3bf7ee0d316f60239c5132a5b1115",
- "sha256:7a01dced9d7880b4107b0b7fe65fc427c8886f26f36e4ada6eec809259742767",
- "sha256:7d56c36ea9a71edb2aacdf5f628d31a9ffbf4bde025b1c9b77f707e8400dd910",
- "sha256:7f6f710e7fd07adafdda139d4d43f358da666db2544608eabf0a43b1fb5dc5a4",
- "sha256:8be68d1ddbb7a21ae2df8bf9621b7f6cc6bb6a15a49e76e105bd7fe9d88b84b3",
- "sha256:8cf102e4b7ff37e6303b310ec38585a153a31c1eed3b5ceeae0df6f01d35ae01",
- "sha256:94b3bae28d5811c400673918a0dd656f6deeb691b3530f25ee367180c822dfbe",
- "sha256:9d122c30c731226efab9d1454919bb6595275345754513017b5798378f748200",
- "sha256:a2062458a8b3646a13a93dbd557b46f57d6fc884486d4f14b1cb232c4014c03c",
- "sha256:a39205e3e0d30a35cdab72fd22808db561599cb95e7c73ca6a113b7273f15529",
- "sha256:a6c4ebb9a8c5dfa5ad8547a78b34550c2968a1ab2fe0c29a5af2e71d53a1da6b",
- "sha256:a7fcfd5fadc91828bb9b0f7a8699f6c7ae900131b095e79bb1c5ca211bf9acd5",
- "sha256:a9389e8b5fe55b1a1b62ccbcf8df55907bbe0250536bf39c2686f6d40d6c3e5a",
- "sha256:b82470b9719dcccd1e26db132af055d5dd2fedd347ba272cc3788bf4723314de",
- "sha256:bd6aca8554745760b3aade96586272fd724438b20aaa2c7335ffb8bab293e852",
- "sha256:c1c5043fdc10629debabadb21854d8ff9f5642103d61f02df71104a270c2d0cc",
- "sha256:d8cd6bc002b1725da0937cb5e789cb71bee6b05de90b436a2448a47ac64c9196",
- "sha256:db9332d5b6040c3c0c6eed54fcd75b6fd592a219734c7bfb1cc5ecced82f0683",
- "sha256:dbddf8921a3b19cfa09ad35a6a02d82f545cacd6d8e5d1dc41e26a2a468e43e9",
- "sha256:e649cda58ebc5480e83db0fa217751ea5e73b3bd556ff019319acdf9a381d67c",
- "sha256:feb72207824d0e77fc5c13ade0f5c9207ce0e4d0b14aa30e7e0e16f61ec36b25"
- ],
- "index": "pypi",
- "version": "==2.0.0.dev6"
+ "sha256:010c2e49f15de8ca24e15ce51df6911f5d0804f2c484bd9c67ffc8ed78e452f0",
+ "sha256:0267b4def5c07e3b08329f80cb51c8c457d514221f6a2d5ec175569bd02280c9",
+ "sha256:071f0e4d50a5af008a86d43236fc3dc0a903fc6dab1872b4282e1022e8b888b6",
+ "sha256:0b3b26f6ad21a651301acf48c48fdc541bd3dbbdeb214d82bbad5c9403ed71e8",
+ "sha256:10743ba4d4d07fb2437f7399fe65b99b99202b92899b0b8f085d3f97bdd408e0",
+ "sha256:10ea85a1a2a06de7e9ee4b52c391f574104017bdc8a5569d92a95d4b6e4df9cc",
+ "sha256:1162be5304d72e84d173c1c0cfa68ba742a6d20f166095e945ee8f3952a25a25",
+ "sha256:1361dbc180786f17fe399f632a0809881bbaa588c094a613a5d139f0a9f5bb17",
+ "sha256:1f2d9df9374677a963d41e3247eea9a9da768a8556d055ffbd55fff0a48d8a1a",
+ "sha256:1f648ee199a7359b8bdd9534fbbb6d046910ed821ca565d23083eb4e128b38ce",
+ "sha256:370202bbc33b5747986eee24f44e2e84d5fb18a48398ec944018c288e9298874",
+ "sha256:56eefff1c9c4338533673f4cb00c975b1a807d41b429a66ecd6e0cae274b99b2",
+ "sha256:660ab9e8dd960d312f0bd1b0b7b62d22891fb6e188ebd980cc78d57336d067d2",
+ "sha256:68c3a9224bb9e878f244aad9cd842ccef10e9c074c6284b61ec2fd9931e67def",
+ "sha256:71d629fae5b20a88cdbf541abc4f2025b823731ee73b8b2380d9c86160640d11",
+ "sha256:7ae141466b6783abeaf66e10884a2824b3e47ab681f411e83b5c9884e15ba81b",
+ "sha256:7df846da4d24e85a38240e1bcc1d5579d72e4a8b675b4bc77aad899cb8d53feb",
+ "sha256:7fd14b068e784b118b51eda271a8fc3bfe2b0c54b6146ac6e34f66858ac27834",
+ "sha256:8068af05b2a2fc9984e55ad05f9131ec767b2fc312df0f50972e88c4485f5d8e",
+ "sha256:83029fa1ad72bf07aa6a6c8e05cfc5d1a07c08c648d21dfb3176d38c8f0db3b4",
+ "sha256:842f8991ae60c93493d548b34da4d9c9523eaa066d5dc849273cec080f9b46b8",
+ "sha256:8a80cff2fd8818daec3b084b4caa5c5ecbe2a2460d9c10f96682350032c3b5fe",
+ "sha256:921d6565b40ff3da1e505efa1f75f0438214ca0d6b413e19a481fb52bff1ca7a",
+ "sha256:96bc63d8e56998f079d1d92e077213935f3dea800300912e4176c2a300135e13",
+ "sha256:a0fe0dcdbba303cd5dd01d46231cbeabf0bbe2f9c88e6066458c8eeb584352de",
+ "sha256:b47875c58b507b74361cecd0083411e0b19ae15dff7da45e104da86d8a1fefcb",
+ "sha256:bdeb5399d90d352a393c2461ff19f2d627c602706be7ea1415021b4862ce720d",
+ "sha256:d4e0cd3392ebc88c321175b205ebeb0c3247ceb2468d940d90fcb849075b468f",
+ "sha256:d72e3a583b081058107e5157b706cc409b3afdae892f560481ef298fd4154a29",
+ "sha256:d76183fa2a6070006d0f8e95fb707edface752564248f63267bdd98464b55feb",
+ "sha256:da1d869fb24e2f852c259b79e80f47c6f38a1176f872bb79aa866ca79b052867",
+ "sha256:e63c0d05c384337b3354e6368769204f0b965b092d167f55eea26e13e97208d8",
+ "sha256:ecad810029f8058712ae649588fc0b2faaf0746be84aa225de285b2a000aba8f",
+ "sha256:f6d0ea74b97a487e1f491c75386d494ecd573851af4e08090eacfa707ba43428"
+ ],
+ "index": "pypi",
+ "version": "==2.0.0.dev8"
},
"pygments": {
"hashes": [
@@ -2169,11 +2267,11 @@
},
"pylint": {
"hashes": [
- "sha256:b95e31850f3af163c2283ed40432f053acbc8fc6eba6a069cb518d9dbf71848c",
- "sha256:dd506acce0427e9e08fb87274bcaa953d38b50a58207170dbf5b36cf3e16957b"
+ "sha256:7dd78437f2d8d019717dbf287772d0b2dbdfd13fc016aa7faa08d67bccc46adc",
+ "sha256:d0ece7d223fe422088b0e8f13fa0a1e8eb745ebffcb8ed53d3e95394b6101a1c"
],
"index": "pypi",
- "version": "==2.5.2"
+ "version": "==2.5.3"
},
"pylogbeat": {
"hashes": [
@@ -2184,99 +2282,93 @@
},
"pymongo": {
"hashes": [
- "sha256:01b4e10027aef5bb9ecefbc26f5df3368ce34aef81df43850f701e716e3fe16d",
- "sha256:0fc5aa1b1acf7f61af46fe0414e6a4d0c234b339db4c03a63da48599acf1cbfc",
- "sha256:1396eb7151e0558b1f817e4b9d7697d5599e5c40d839a9f7270bd90af994ad82",
- "sha256:18e84a3ec5e73adcb4187b8e5541b2ad61d716026ed9863267e650300d8bea33",
- "sha256:19adf2848b80cb349b9891cc854581bbf24c338be9a3260e73159bdeb2264464",
- "sha256:20ee0475aa2ba437b0a14806f125d696f90a8433d820fb558fdd6f052acde103",
- "sha256:26798795097bdeb571f13942beef7e0b60125397811c75b7aa9214d89880dd1d",
- "sha256:26e707a4eb851ec27bb969b5f1413b9b2eac28fe34271fa72329100317ea7c73",
- "sha256:2a3c7ad01553b27ec553688a1e6445e7f40355fb37d925c11fcb50b504e367f8",
- "sha256:2f07b27dbf303ea53f4147a7922ce91a26b34a0011131471d8aaf73151fdee9a",
- "sha256:316f0cf543013d0c085e15a2c8abe0db70f93c9722c0f99b6f3318ff69477d70",
- "sha256:31d11a600eea0c60de22c8bdcb58cda63c762891facdcb74248c36713240987f",
- "sha256:334ef3ffd0df87ea83a0054454336159f8ad9c1b389e19c0032d9cb8410660e6",
- "sha256:358ba4693c01022d507b96a980ded855a32dbdccc3c9331d0667be5e967f30ed",
- "sha256:3a6568bc53103df260f5c7d2da36dffc5202b9a36c85540bba1836a774943794",
- "sha256:444bf2f44264578c4085bb04493bfed0e5c1b4fe7c2704504d769f955cc78fe4",
- "sha256:47a00b22c52ee59dffc2aad02d0bbfb20c26ec5b8de8900492bf13ad6901cf35",
- "sha256:4c067db43b331fc709080d441cb2e157114fec60749667d12186cc3fc8e7a951",
- "sha256:4c092310f804a5d45a1bcaa4191d6d016c457b6ed3982a622c35f729ff1c7f6b",
- "sha256:53b711b33134e292ef8499835a3df10909c58df53a2a0308f598c432e9a62892",
- "sha256:568d6bee70652d8a5af1cd3eec48b4ca1696fb1773b80719ebbd2925b72cb8f6",
- "sha256:56fa55032782b7f8e0bf6956420d11e2d4e9860598dfe9c504edec53af0fc372",
- "sha256:5a2c492680c61b440272341294172fa3b3751797b1ab983533a770e4fb0a67ac",
- "sha256:61235cc39b5b2f593086d1d38f3fc130b2d125bd8fc8621d35bc5b6bdeb92bd2",
- "sha256:619ac9aaf681434b4d4718d1b31aa2f0fce64f2b3f8435688fcbdc0c818b6c54",
- "sha256:6238ac1f483494011abde5286282afdfacd8926659e222ba9b74c67008d3a58c",
- "sha256:63752a72ca4d4e1386278bd43d14232f51718b409e7ac86bcf8810826b531113",
- "sha256:6fdc5ccb43864065d40dd838437952e9e3da9821b7eac605ba46ada77f846bdf",
- "sha256:7abc3a6825a346fa4621a6f63e3b662bbb9e0f6ffc32d30a459d695f20fb1a8b",
- "sha256:7aef381bb9ae8a3821abd7f9d4d93978dbd99072b48522e181baeffcd95b56ae",
- "sha256:80df3caf251fe61a3f0c9614adc6e2bfcffd1cd3345280896766712fb4b4d6d7",
- "sha256:95f970f34b59987dee6f360d2e7d30e181d58957b85dff929eee4423739bd151",
- "sha256:993257f6ca3cde55332af1f62af3e04ca89ce63c08b56a387cdd46136c72f2fa",
- "sha256:9c0a57390549affc2b5dda24a38de03a5c7cbc58750cd161ff5d106c3c6eec80",
- "sha256:a0794e987d55d2f719cc95fcf980fc62d12b80e287e6a761c4be14c60bd9fecc",
- "sha256:a3b98121e68bf370dd8ea09df67e916f93ea95b52fc010902312168c4d1aff5d",
- "sha256:a60756d55f0887023b3899e6c2923ba5f0042fb11b1d17810b4e07395404f33e",
- "sha256:a676bd2fbc2309092b9bbb0083d35718b5420af3a42135ebb1e4c3633f56604d",
- "sha256:a732838c78554c1257ff2492f5c8c4c7312d0aecd7f732149e255f3749edd5ee",
- "sha256:ad3dc88dfe61f0f1f9b99c6bc833ea2f45203a937a18f0d2faa57c6952656012",
- "sha256:ae65d65fde4135ef423a2608587c9ef585a3551fc2e4e431e7c7e527047581be",
- "sha256:b070a4f064a9edb70f921bfdc270725cff7a78c22036dd37a767c51393fb956f",
- "sha256:b6da85949aa91e9f8c521681344bd2e163de894a5492337fba8b05c409225a4f",
- "sha256:bbf47110765b2a999803a7de457567389253f8670f7daafb98e059c899ce9764",
- "sha256:bd9c1e6f92b4888ae3ef7ae23262c513b962f09f3fb3b48581dde5df7d7a860a",
- "sha256:c06b3f998d2d7160db58db69adfb807d2ec307e883e2f17f6b87a1ef6c723f11",
- "sha256:c318fb70542be16d3d4063cde6010b1e4d328993a793529c15a619251f517c39",
- "sha256:c4aef42e5fa4c9d5a99f751fb79caa880dac7eaf8a65121549318b984676a1b7",
- "sha256:c9ca545e93a9c2a3bdaa2e6e21f7a43267ff0813e8055adf2b591c13164c0c57",
- "sha256:da2c3220eb55c4239dd8b982e213da0b79023cac59fe54ca09365f2bc7e4ad32",
- "sha256:dd8055da300535eefd446b30995c0813cc4394873c9509323762a93e97c04c03",
- "sha256:e2b46e092ea54b732d98c476720386ff2ccd126de1e52076b470b117bff7e409",
- "sha256:e334c4f39a2863a239d38b5829e442a87f241a92da9941861ee6ec5d6380b7fe",
- "sha256:e5c54f04ca42bbb5153aec5d4f2e3d9f81e316945220ac318abd4083308143f5",
- "sha256:f4d06764a06b137e48db6d569dc95614d9d225c89842c885669ee8abc9f28c7a",
- "sha256:f96333f9d2517c752c20a35ff95de5fc2763ac8cdb1653df0f6f45d281620606"
- ],
- "index": "pypi",
- "version": "==3.10.1"
+ "sha256:03dc64a9aa7a5d405aea5c56db95835f6a2fa31b3502c5af1760e0e99210be30",
+ "sha256:05fcc6f9c60e6efe5219fbb5a30258adb3d3e5cbd317068f3d73c09727f2abb6",
+ "sha256:076a7f2f7c251635cf6116ac8e45eefac77758ee5a77ab7bd2f63999e957613b",
+ "sha256:137e6fa718c7eff270dbd2fc4b90d94b1a69c9e9eb3f3de9e850a7fd33c822dc",
+ "sha256:1f865b1d1c191d785106f54df9abdc7d2f45a946b45fd1ea0a641b4f982a2a77",
+ "sha256:213c445fe7e654621c6309e874627c35354b46ef3ee807f5a1927dc4b30e1a67",
+ "sha256:25e617daf47d8dfd4e152c880cd0741cbdb48e51f54b8de9ddbfe74ecd87dd16",
+ "sha256:3d9bb1ba935a90ec4809a8031efd988bdb13cdba05d9e9a3e9bf151bf759ecde",
+ "sha256:40696a9a53faa7d85aaa6fd7bef1cae08f7882640bad08c350fb59dee7ad069b",
+ "sha256:421aa1b92c291c429668bd8d8d8ec2bd00f183483a756928e3afbf2b6f941f00",
+ "sha256:4437300eb3a5e9cc1a73b07d22c77302f872f339caca97e9bf8cf45eca8fa0d2",
+ "sha256:455f4deb00158d5ec8b1d3092df6abb681b225774ab8a59b3510293b4c8530e3",
+ "sha256:475a34a0745c456ceffaec4ce86b7e0983478f1b6140890dff7b161e7bcd895b",
+ "sha256:4797c0080f41eba90404335e5ded3aa66731d303293a675ff097ce4ea3025bb9",
+ "sha256:4ae23fbbe9eadf61279a26eba866bbf161a6f7e2ffad14a42cf20e9cb8e94166",
+ "sha256:4b32744901ee9990aa8cd488ec85634f443526def1e5190a407dc107148249d7",
+ "sha256:50127b13b38e8e586d5e97d342689405edbd74ad0bd891d97ee126a8c7b6e45f",
+ "sha256:50531caa7b4be1c4ed5e2d5793a4e51cc9bd62a919a6fd3299ef7c902e206eab",
+ "sha256:63a5387e496a98170ffe638b435c0832c0f2011a6f4ff7a2880f17669fff8c03",
+ "sha256:68220b81850de8e966d4667d5c325a96c6ac0d6adb3d18935d6e3d325d441f48",
+ "sha256:689142dc0c150e9cb7c012d84cac2c346d40beb891323afb6caf18ec4caafae0",
+ "sha256:6a15e2bee5c4188369a87ed6f02de804651152634a46cca91966a11c8abd2550",
+ "sha256:7122ffe597b531fb065d3314e704a6fe152b81820ca5f38543e70ffcc95ecfd4",
+ "sha256:7307024b18266b302f4265da84bb1effb5d18999ef35b30d17592959568d5c0a",
+ "sha256:7a4a6f5b818988a3917ec4baa91d1143242bdfece8d38305020463955961266a",
+ "sha256:83c5a3ecd96a9f3f11cfe6dfcbcec7323265340eb24cc996acaecea129865a3a",
+ "sha256:890b0f1e18dbd898aeb0ab9eae1ab159c6bcbe87f0abb065b0044581d8614062",
+ "sha256:8deda1f7b4c03242f2a8037706d9584e703f3d8c74d6d9cac5833db36fe16c42",
+ "sha256:8ea13d0348b4c96b437d944d7068d59ed4a6c98aaa6c40d8537a2981313f1c66",
+ "sha256:91e96bf85b7c07c827d339a386e8a3cf2e90ef098c42595227f729922d0851df",
+ "sha256:96782ebb3c9e91e174c333208b272ea144ed2a684413afb1038e3b3342230d72",
+ "sha256:9755c726aa6788f076114dfdc03b92b03ff8860316cca00902cce88bcdb5fedd",
+ "sha256:9dbab90c348c512e03f146e93a5e2610acec76df391043ecd46b6b775d5397e6",
+ "sha256:9ee0eef254e340cc11c379f797af3977992a7f2c176f1a658740c94bf677e13c",
+ "sha256:9fc17fdac8f1973850d42e51e8ba6149d93b1993ed6768a24f352f926dd3d587",
+ "sha256:a2787319dc69854acdfd6452e6a8ba8f929aeb20843c7f090e04159fc18e6245",
+ "sha256:b7c522292407fa04d8195032493aac937e253ad9ae524aab43b9d9d242571f03",
+ "sha256:bd312794f51e37dcf77f013d40650fe4fbb211dd55ef2863839c37480bd44369",
+ "sha256:c0d660a186e36c526366edf8a64391874fe53cf8b7039224137aee0163c046df",
+ "sha256:c4869141e20769b65d2d72686e7a7eb141ce9f3168106bed3e7dcced54eb2422",
+ "sha256:cc4057f692ac35bbe82a0a908d42ce3a281c9e913290fac37d7fa3bd01307dfb",
+ "sha256:cccf1e7806f12300e3a3b48f219e111000c2538483e85c869c35c1ae591e6ce9",
+ "sha256:ce208f80f398522e49d9db789065c8ad2cd37b21bd6b23d30053474b7416af11",
+ "sha256:d0565481dc196986c484a7fb13214fc6402201f7fb55c65fd215b3324962fe6c",
+ "sha256:d1b3366329c45a474b3bbc9b9c95d4c686e03f35da7fd12bc144626d1f2a7c04",
+ "sha256:d226e0d4b9192d95079a9a29c04dd81816b1ce8903b8c174a39224fe978547cb",
+ "sha256:d38b35f6eef4237b1d0d8e845fc1546dad85c55eba447e28c211da8c7ef9697c",
+ "sha256:d64c98277ea80e4484f1332ab107e8dfd173a7dcf1bdbf10a9cccc97aaab145f",
+ "sha256:d9de8427a5601799784eb0e7fa1b031aa64086ce04de29df775a8ca37eedac41",
+ "sha256:e6a15cf8f887d9f578dd49c6fb3a99d53e1d922fdd67a245a67488d77bf56eb2",
+ "sha256:e8c446882cbb3774cd78c738c9f58220606b702b7c1655f1423357dc51674054",
+ "sha256:e8d188ee39bd0ffe76603da887706e4e7b471f613625899ddf1e27867dc6a0d3",
+ "sha256:ef76535776c0708a85258f6dc51d36a2df12633c735f6d197ed7dfcaa7449b99",
+ "sha256:f6efca006a81e1197b925a7d7b16b8f61980697bb6746587aad8842865233218"
+ ],
+ "index": "pypi",
+ "version": "==3.11.0"
},
"pymysql": {
"hashes": [
- "sha256:95f057328357e0e13a30e67857a8c694878b0175797a9a203ee7adbfb9b1ec5f",
- "sha256:9ec760cbb251c158c19d6c88c17ca00a8632bac713890e465b2be01fdc30713f"
+ "sha256:adef15ceccf1ff544a23a6f46609f65187261dc8b0cf94c9644189c173b0a451",
+ "sha256:e14070bc84e050e0f80bf6063e31d276f03a0bb4d46b9eca2854566c4ae19837"
],
"index": "pypi",
- "version": "==0.9.2"
+ "version": "==0.10.0"
},
"pynacl": {
"hashes": [
- "sha256:05c26f93964373fc0abe332676cb6735f0ecad27711035b9472751faa8521255",
- "sha256:0c6100edd16fefd1557da078c7a31e7b7d7a52ce39fdca2bec29d4f7b6e7600c",
- "sha256:0d0a8171a68edf51add1e73d2159c4bc19fc0718e79dec51166e940856c2f28e",
- "sha256:1c780712b206317a746ace34c209b8c29dbfd841dfbc02aa27f2084dd3db77ae",
- "sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621",
- "sha256:2d23c04e8d709444220557ae48ed01f3f1086439f12dbf11976e849a4926db56",
- "sha256:30f36a9c70450c7878053fa1344aca0145fd47d845270b43a7ee9192a051bf39",
- "sha256:37aa336a317209f1bb099ad177fef0da45be36a2aa664507c5d72015f956c310",
- "sha256:4943decfc5b905748f0756fdd99d4f9498d7064815c4cf3643820c9028b711d1",
- "sha256:53126cd91356342dcae7e209f840212a58dcf1177ad52c1d938d428eebc9fee5",
- "sha256:57ef38a65056e7800859e5ba9e6091053cd06e1038983016effaffe0efcd594a",
- "sha256:5bd61e9b44c543016ce1f6aef48606280e45f892a928ca7068fba30021e9b786",
- "sha256:6482d3017a0c0327a49dddc8bd1074cc730d45db2ccb09c3bac1f8f32d1eb61b",
- "sha256:7d3ce02c0784b7cbcc771a2da6ea51f87e8716004512493a2b69016326301c3b",
- "sha256:a14e499c0f5955dcc3991f785f3f8e2130ed504fa3a7f44009ff458ad6bdd17f",
- "sha256:a39f54ccbcd2757d1d63b0ec00a00980c0b382c62865b61a505163943624ab20",
- "sha256:aabb0c5232910a20eec8563503c153a8e78bbf5459490c49ab31f6adf3f3a415",
- "sha256:bd4ecb473a96ad0f90c20acba4f0bf0df91a4e03a1f4dd6a4bdc9ca75aa3a715",
- "sha256:bf459128feb543cfca16a95f8da31e2e65e4c5257d2f3dfa8c0c1031139c9c92",
- "sha256:e2da3c13307eac601f3de04887624939aca8ee3c9488a0bb0eca4fb9401fc6b1",
- "sha256:f67814c38162f4deb31f68d590771a29d5ae3b1bd64b75cf232308e5c74777e0"
+ "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4",
+ "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4",
+ "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574",
+ "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d",
+ "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25",
+ "sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f",
+ "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505",
+ "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122",
+ "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7",
+ "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420",
+ "sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f",
+ "sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96",
+ "sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6",
+ "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514",
+ "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff",
+ "sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"
],
- "version": "==1.3.0"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.4.0"
},
"pynmea2": {
"hashes": [
@@ -2353,10 +2445,10 @@
},
"python-engineio": {
"hashes": [
- "sha256:222926adb4bc6e03a8fc8e0ef2a3309f030c1c3f8e0fcc94c9ba214574565f02",
- "sha256:2481732d93646998f7372ef0ecf003af7817b82720b881db173c3d50b4887916"
+ "sha256:133bdb5fb89f43a53f8612fb1ddbb3a453318713dea18a9ecf5346ed0c0f793c",
+ "sha256:41353c2539493e9e30e0e75e53f9cbb670f09a5ebcf82fe738081a9ba28fe55c"
],
- "version": "==3.12.1"
+ "version": "==3.13.1"
},
"python-logstash": {
"hashes": [
@@ -2367,18 +2459,18 @@
},
"python-logstash-async": {
"hashes": [
- "sha256:96492d7080bd197baf889d3ea927206e987161e08d3fce9cfb0557c6c6d4013e",
- "sha256:c07d7f80d06b807ac8ab613562d7f246056ffb57320e60c714cd421ff053c2c2"
+ "sha256:56b0fd4c06ede320d7f1defa6b4f6b442227a880ce84f44c88b69c313e35cd6f",
+ "sha256:57aebfccd8a7e0ee5b7c4bdb7c941e84eac3c3e30c5619feabb5444d9b827d2b"
],
"index": "pypi",
- "version": "==1.6.4"
+ "version": "==1.6.6"
},
"python-socketio": {
"hashes": [
- "sha256:149b98c33f8c3d09273fb4ebeb83781e4dc9411b56b27d9f058bec1bd1ed74b7",
- "sha256:81280cbbb7018d8ecdd006bf6025979733d347c0f2612282c1e21f6ed7d3b55b"
+ "sha256:358d8fbbc029c4538ea25bcaa283e47f375be0017fcba829de8a3a731c9df25a",
+ "sha256:d437f797c44b6efba2f201867cf02b8c96b97dff26d4e4281ac08b45817cd522"
],
- "version": "==4.5.1"
+ "version": "==4.6.0"
},
"pytz": {
"hashes": [
@@ -2433,44 +2525,44 @@
},
"pyzmq": {
"hashes": [
- "sha256:07fb8fe6826a229dada876956590135871de60dbc7de5a18c3bcce2ed1f03c98",
- "sha256:13a5638ab24d628a6ade8f794195e1a1acd573496c3b85af2f1183603b7bf5e0",
- "sha256:15b4cb21118f4589c4db8be4ac12b21c8b4d0d42b3ee435d47f686c32fe2e91f",
- "sha256:21f7d91f3536f480cb2c10d0756bfa717927090b7fb863e6323f766e5461ee1c",
- "sha256:2a88b8fabd9cc35bd59194a7723f3122166811ece8b74018147a4ed8489e6421",
- "sha256:342fb8a1dddc569bc361387782e8088071593e7eaf3e3ecf7d6bd4976edff112",
- "sha256:4ee0bfd82077a3ff11c985369529b12853a4064320523f8e5079b630f9551448",
- "sha256:54aa24fd60c4262286fc64ca632f9e747c7cc3a3a1144827490e1dc9b8a3a960",
- "sha256:58688a2dfa044fad608a8e70ba8d019d0b872ec2acd75b7b5e37da8905605891",
- "sha256:5b99c2ae8089ef50223c28bac57510c163bfdff158c9e90764f812b94e69a0e6",
- "sha256:5b9d21fc56c8aacd2e6d14738021a9d64f3f69b30578a99325a728e38a349f85",
- "sha256:5f1f2eb22aab606f808163eb1d537ac9a0ba4283fbeb7a62eb48d9103cf015c2",
- "sha256:6ca519309703e95d55965735a667809bbb65f52beda2fdb6312385d3e7a6d234",
- "sha256:87c78f6936e2654397ca2979c1d323ee4a889eef536cc77a938c6b5be33351a7",
- "sha256:8952f6ba6ae598e792703f3134af5a01af8f5c7cf07e9a148f05a12b02412cea",
- "sha256:931339ac2000d12fe212e64f98ce291e81a7ec6c73b125f17cf08415b753c087",
- "sha256:956775444d01331c7eb412c5fb9bb62130dfaac77e09f32764ea1865234e2ca9",
- "sha256:97b6255ae77328d0e80593681826a0479cb7bac0ba8251b4dd882f5145a2293a",
- "sha256:aaa8b40b676576fd7806839a5de8e6d5d1b74981e6376d862af6c117af2a3c10",
- "sha256:af0c02cf49f4f9eedf38edb4f3b6bb621d83026e7e5d76eb5526cc5333782fd6",
- "sha256:b08780e3a55215873b3b8e6e7ca8987f14c902a24b6ac081b344fd430d6ca7cd",
- "sha256:ba6f24431b569aec674ede49cad197cad59571c12deed6ad8e3c596da8288217",
- "sha256:bafd651b557dd81d89bd5f9c678872f3e7b7255c1c751b78d520df2caac80230",
- "sha256:bfff5ffff051f5aa47ba3b379d87bd051c3196b0c8a603e8b7ed68a6b4f217ec",
- "sha256:cf5d689ba9513b9753959164cf500079383bc18859f58bf8ce06d8d4bef2b054",
- "sha256:dcbc3f30c11c60d709c30a213dc56e88ac016fe76ac6768e64717bd976072566",
- "sha256:f9d7e742fb0196992477415bb34366c12e9bb9a0699b8b3f221ff93b213d7bec",
- "sha256:faee2604f279d31312bc455f3d024f160b6168b9c1dde22bf62d8c88a4deca8e"
- ],
- "index": "pypi",
- "version": "==19.0.1"
+ "sha256:00dca814469436455399660247d74045172955459c0bd49b54a540ce4d652185",
+ "sha256:046b92e860914e39612e84fa760fc3f16054d268c11e0e25dcb011fb1bc6a075",
+ "sha256:09d24a80ccb8cbda1af6ed8eb26b005b6743e58e9290566d2a6841f4e31fa8e0",
+ "sha256:0a422fc290d03958899743db091f8154958410fc76ce7ee0ceb66150f72c2c97",
+ "sha256:276ad604bffd70992a386a84bea34883e696a6b22e7378053e5d3227321d9702",
+ "sha256:296540a065c8c21b26d63e3cea2d1d57902373b16e4256afe46422691903a438",
+ "sha256:29d51279060d0a70f551663bc592418bcad7f4be4eea7b324f6dd81de05cb4c1",
+ "sha256:36ab114021c0cab1a423fe6689355e8f813979f2c750968833b318c1fa10a0fd",
+ "sha256:3fa6debf4bf9412e59353defad1f8035a1e68b66095a94ead8f7a61ae90b2675",
+ "sha256:5120c64646e75f6db20cc16b9a94203926ead5d633de9feba4f137004241221d",
+ "sha256:59f1e54627483dcf61c663941d94c4af9bf4163aec334171686cdaee67974fe5",
+ "sha256:5d9fc809aa8d636e757e4ced2302569d6e60e9b9c26114a83f0d9d6519c40493",
+ "sha256:654d3e06a4edc566b416c10293064732516cf8871a4522e0a2ba00cc2a2e600c",
+ "sha256:720d2b6083498a9281eaee3f2927486e9fe02cd16d13a844f2e95217f243efea",
+ "sha256:73483a2caaa0264ac717af33d6fb3f143d8379e60a422730ee8d010526ce1913",
+ "sha256:8a6ada5a3f719bf46a04ba38595073df8d6b067316c011180102ba2a1925f5b5",
+ "sha256:8b66b94fe6243d2d1d89bca336b2424399aac57932858b9a30309803ffc28112",
+ "sha256:99cc0e339a731c6a34109e5c4072aaa06d8e32c0b93dc2c2d90345dd45fa196c",
+ "sha256:a7e7f930039ee0c4c26e4dfee015f20bd6919cd8b97c9cd7afbde2923a5167b6",
+ "sha256:ab0d01148d13854de716786ca73701012e07dff4dfbbd68c4e06d8888743526e",
+ "sha256:c1a31cd42905b405530e92bdb70a8a56f048c8a371728b8acf9d746ecd4482c0",
+ "sha256:c20dd60b9428f532bc59f2ef6d3b1029a28fc790d408af82f871a7db03e722ff",
+ "sha256:c36ffe1e5aa35a1af6a96640d723d0d211c5f48841735c2aa8d034204e87eb87",
+ "sha256:c40fbb2b9933369e994b837ee72193d6a4c35dfb9a7c573257ef7ff28961272c",
+ "sha256:d46fb17f5693244de83e434648b3dbb4f4b0fec88415d6cbab1c1452b6f2ae17",
+ "sha256:e36f12f503511d72d9bdfae11cadbadca22ff632ff67c1b5459f69756a029c19",
+ "sha256:f1a25a61495b6f7bb986accc5b597a3541d9bd3ef0016f50be16dbb32025b302",
+ "sha256:fa411b1d8f371d3a49d31b0789eb6da2537dadbb2aef74a43aa99a78195c3f76"
+ ],
+ "index": "pypi",
+ "version": "==19.0.2"
},
"qtconsole": {
"hashes": [
- "sha256:8f5ae5571f0e921db9f2d12613ed667c350ee22c7db598d9bbbe143e8533f932",
- "sha256:e7882df6e95ec710b5893ec3a7ebfd54e410e63d801e4bbf8c785d74758c2329"
+ "sha256:4f43d0b049eacb7d723772847f0c465feccce0ccb398871a6e146001a22bad23",
+ "sha256:f5cb275d30fc8085e2d1d18bc363e5ba0ce6e559bf37d7d6727b773134298754"
],
- "version": "==4.7.3"
+ "version": "==4.7.5"
},
"qtpy": {
"hashes": [
@@ -2481,19 +2573,19 @@
},
"redis": {
"hashes": [
- "sha256:6e9d2722a95d10ddf854596e66516d316d99c6a483e5db3b35c34e1158b2bfa1",
- "sha256:a5b0e25890d216d8189636742c50ab992e42eea699bcc1b08cc2d6bf3adff52a"
+ "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2",
+ "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"
],
"index": "pypi",
- "version": "==3.5.1"
+ "version": "==3.5.3"
},
"requests": {
"hashes": [
- "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
- "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
+ "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b",
+ "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"
],
"index": "pypi",
- "version": "==2.23.0"
+ "version": "==2.24.0"
},
"requests-oauthlib": {
"hashes": [
@@ -2512,10 +2604,11 @@
},
"rsa": {
"hashes": [
- "sha256:14ba45700ff1ec9eeb206a2ce76b32814958a98e372006c8fb76ba820211be66",
- "sha256:1a836406405730121ae9823e19c6e806c62bbad73f890574fff50efa4122c487"
+ "sha256:109ea5a66744dd859bf16fe904b8d8b627adafb9408753161e766a92e7d681fa",
+ "sha256:6166864e23d6b5195a5cfed6cd9fed0fe774e226d8f854fcb23b7bbef0350233"
],
- "version": "==4.0"
+ "markers": "python_version >= '3.5'",
+ "version": "==4.6"
},
"s2sphere": {
"hashes": [
@@ -2534,22 +2627,22 @@
},
"scikit-image": {
"hashes": [
- "sha256:11bcc65ca2927c1842212b37ab64fe589a3eb6de375ea09cea0d7cd99bbde418",
- "sha256:1247803e7afad51b4257fc6e7187eb4da63c8d8d2d51888baaca818b3a814ca9",
- "sha256:1e2e2cf2572549bdb20b88a0f0ac275eea9f04f78b2b6973afdc3f329a73c75c",
- "sha256:45629ef09d96739a575136fa28a8fd0b709d132325a140cdc8c8375df180c456",
- "sha256:9cb106875c11236e4b1a04725c86745e2d65b32887cd2febbd0061c88491181b",
- "sha256:a5d5d38842eaeb8feaa8427fb76240208feefc8d1b0afe109999a5458fe07455",
- "sha256:a5f0c923ebac6e53286c07df79141e236cc161a463ea4a9edf4042a9db495e7b",
- "sha256:acd5e9176e1fbc2ed869cc781b128471ffd3e1e60b267ffc532230c4dc2808df",
- "sha256:bec5ea27cd975cbdcd1688c8631852f578e63bd26a4645dd03ed6f596fe2fc24",
- "sha256:d402c947b9af4e42c875e4b80bad26c8aced87b791931d6ca020dc509ec7e108",
- "sha256:d42c6b87e25905e867c4038a08ef790ba1ac7764a1830a4bb89955d159e69ff4",
- "sha256:f4cd4464792d744c6f4c1cf7f0aea9945ea7664eaf5124f783703a1df80560f5",
- "sha256:ff9521c170b4f8081825e675879f2cbd14f4a7572111fad8fc2c6ec82ba705f3"
+ "sha256:113bcacdfc839854f527a166a71768708328208e7b66e491050d6a57fa6727c7",
+ "sha256:11eec2e65cd4cd6487fe1089aa3538dbe25525aec7a36f5a0f14145df0163ce7",
+ "sha256:178210582cc62a5b25c633966658f1f2598615f9c3f27f36cf45055d2a74b401",
+ "sha256:1fda9109a19dc9d7a4ac152d1fc226fed7282ad186a099f14c0aa9151f0c758e",
+ "sha256:6b65a103edbc34b22640daf3b084dc9e470c358d3298c10aa9e3b424dcc02db6",
+ "sha256:7bedd3881ca4fea657a894815bcd5e5bf80944c26274f6b6417bb770c3f4f8e6",
+ "sha256:86a834f9a4d30201c0803a48a25364fe8f93f9feb3c58f2c483d3ce0a3e5fe4a",
+ "sha256:87ca5168c6fc36b7a298a1db2d185a8298f549854342020f282f747a4e4ddce9",
+ "sha256:bd954c0588f0f7e81d9763dc95e06950e68247d540476e06cb77bcbcd8c2d8b3",
+ "sha256:c0876e562991b0babff989ff4d00f35067a2ddef82e5fdd895862555ffbaec25",
+ "sha256:c5c277704b12e702e34d1f7b7a04d5ee8418735f535d269c74c02c6c9f8abee2",
+ "sha256:e99fa7514320011b250a21ab855fdd61ddcc05d3c77ec9e8f13edcc15d3296b5",
+ "sha256:ee3db438b5b9f8716a91ab26a61377a8a63356b186706f5b979822cc7241006d"
],
"index": "pypi",
- "version": "==0.17.1"
+ "version": "==0.17.2"
},
"scipy": {
"hashes": [
@@ -2620,74 +2713,101 @@
},
"simplejson": {
"hashes": [
- "sha256:0fe3994207485efb63d8f10a833ff31236ed27e3b23dadd0bf51c9900313f8f2",
- "sha256:17163e643dbf125bb552de17c826b0161c68c970335d270e174363d19e7ea882",
- "sha256:1d1e929cdd15151f3c0b2efe953b3281b2fd5ad5f234f77aca725f28486466f6",
- "sha256:1d346c2c1d7dd79c118f0cc7ec5a1c4127e0c8ffc83e7b13fc5709ff78c9bb84",
- "sha256:1ea59f570b9d4916ae5540a9181f9c978e16863383738b69a70363bc5e63c4cb",
- "sha256:1fbba86098bbfc1f85c5b69dc9a6d009055104354e0d9880bb00b692e30e0078",
- "sha256:229edb079d5dd81bf12da952d4d825bd68d1241381b37d3acf961b384c9934de",
- "sha256:22a7acb81968a7c64eba7526af2cf566e7e2ded1cb5c83f0906b17ff1540f866",
- "sha256:2b4b2b738b3b99819a17feaf118265d0753d5536049ea570b3c43b51c4701e81",
- "sha256:4cf91aab51b02b3327c9d51897960c554f00891f9b31abd8a2f50fd4a0071ce8",
- "sha256:4fd5f79590694ebff8dc980708e1c182d41ce1fda599a12189f0ca96bf41ad70",
- "sha256:5cfd495527f8b85ce21db806567de52d98f5078a8e9427b18e251c68bd573a26",
- "sha256:60aad424e47c5803276e332b2a861ed7a0d46560e8af53790c4c4fb3420c26c2",
- "sha256:7739940d68b200877a15a5ff5149e1599737d6dd55e302625650629350466418",
- "sha256:7cce4bac7e0d66f3a080b80212c2238e063211fe327f98d764c6acbc214497fc",
- "sha256:8027bd5f1e633eb61b8239994e6fc3aba0346e76294beac22a892eb8faa92ba1",
- "sha256:86afc5b5cbd42d706efd33f280fec7bd7e2772ef54e3f34cf6b30777cd19a614",
- "sha256:87d349517b572964350cc1adc5a31b493bbcee284505e81637d0174b2758ba17",
- "sha256:8de378d589eccbc75941e480b4d5b4db66f22e4232f87543b136b1f093fff342",
- "sha256:926bcbef9eb60e798eabda9cd0bbcb0fca70d2779aa0aa56845749d973eb7ad5",
- "sha256:9a126c3a91df5b1403e965ba63b304a50b53d8efc908a8c71545ed72535374a3",
- "sha256:ad8dd3454d0c65c0f92945ac86f7b9efb67fa2040ba1b0189540e984df904378",
- "sha256:d140e9376e7f73c1f9e0a8e3836caf5eec57bbafd99259d56979da05a6356388",
- "sha256:da00675e5e483ead345429d4f1374ab8b949fba4429d60e71ee9d030ced64037",
- "sha256:daaf4d11db982791be74b23ff4729af2c7da79316de0bebf880fa2d60bcc8c5a",
- "sha256:f4b64a1031acf33e281fd9052336d6dad4d35eee3404c95431c8c6bc7a9c0588",
- "sha256:fc046afda0ed8f5295212068266c92991ab1f4a50c6a7144b69364bdee4a0159",
- "sha256:fc9051d249dd5512e541f20330a74592f7a65b2d62e18122ca89bf71f94db748"
- ],
- "index": "pypi",
- "version": "==3.17.0"
+ "sha256:034550078a11664d77bc1a8364c90bb7eef0e44c2dbb1fd0a4d92e3997088667",
+ "sha256:05b43d568300c1cd43f95ff4bfcff984bc658aa001be91efb3bb21df9d6288d3",
+ "sha256:0dd9d9c738cb008bfc0862c9b8fa6743495c03a0ed543884bf92fb7d30f8d043",
+ "sha256:10fc250c3edea4abc15d930d77274ddb8df4803453dde7ad50c2f5565a18a4bb",
+ "sha256:2862beabfb9097a745a961426fe7daf66e1714151da8bb9a0c430dde3d59c7c0",
+ "sha256:292c2e3f53be314cc59853bd20a35bf1f965f3bc121e007ab6fd526ed412a85d",
+ "sha256:2d3eab2c3fe52007d703a26f71cf649a8c771fcdd949a3ae73041ba6797cfcf8",
+ "sha256:2e7b57c2c146f8e4dadf84977a83f7ee50da17c8861fd7faf694d55e3274784f",
+ "sha256:311f5dc2af07361725033b13cc3d0351de3da8bede3397d45650784c3f21fbcf",
+ "sha256:344e2d920a7f27b4023c087ab539877a1e39ce8e3e90b867e0bfa97829824748",
+ "sha256:3fabde09af43e0cbdee407555383063f8b45bfb52c361bc5da83fcffdb4fd278",
+ "sha256:42b8b8dd0799f78e067e2aaae97e60d58a8f63582939af60abce4c48631a0aa4",
+ "sha256:4b3442249d5e3893b90cb9f72c7d6ce4d2ea144d2c0d9f75b9ae1e5460f3121a",
+ "sha256:55d65f9cc1b733d85ef95ab11f559cce55c7649a2160da2ac7a078534da676c8",
+ "sha256:5c659a0efc80aaaba57fcd878855c8534ecb655a28ac8508885c50648e6e659d",
+ "sha256:72d8a3ffca19a901002d6b068cf746be85747571c6a7ba12cbcf427bfb4ed971",
+ "sha256:75ecc79f26d99222a084fbdd1ce5aad3ac3a8bd535cd9059528452da38b68841",
+ "sha256:76ac9605bf2f6d9b56abf6f9da9047a8782574ad3531c82eae774947ae99cc3f",
+ "sha256:7d276f69bfc8c7ba6c717ba8deaf28f9d3c8450ff0aa8713f5a3280e232be16b",
+ "sha256:7f10f8ba9c1b1430addc7dd385fc322e221559d3ae49b812aebf57470ce8de45",
+ "sha256:8042040af86a494a23c189b5aa0ea9433769cc029707833f261a79c98e3375f9",
+ "sha256:813846738277729d7db71b82176204abc7fdae2f566e2d9fcf874f9b6472e3e6",
+ "sha256:845a14f6deb124a3bcb98a62def067a67462a000e0508f256f9c18eff5847efc",
+ "sha256:869a183c8e44bc03be1b2bbcc9ec4338e37fa8557fc506bf6115887c1d3bb956",
+ "sha256:8acf76443cfb5c949b6e781c154278c059b09ac717d2757a830c869ba000cf8d",
+ "sha256:8f713ea65958ef40049b6c45c40c206ab363db9591ff5a49d89b448933fa5746",
+ "sha256:934115642c8ba9659b402c8bdbdedb48651fb94b576e3b3efd1ccb079609b04a",
+ "sha256:9551f23e09300a9a528f7af20e35c9f79686d46d646152a0c8fc41d2d074d9b0",
+ "sha256:9a2b7543559f8a1c9ed72724b549d8cc3515da7daf3e79813a15bdc4a769de25",
+ "sha256:a55c76254d7cf8d4494bc508e7abb993a82a192d0db4552421e5139235604625",
+ "sha256:ad8f41c2357b73bc9e8606d2fa226233bf4d55d85a8982ecdfd55823a6959995",
+ "sha256:af4868da7dd53296cd7630687161d53a7ebe2e63814234631445697bd7c29f46",
+ "sha256:afebfc3dd3520d37056f641969ce320b071bc7a0800639c71877b90d053e087f",
+ "sha256:b59aa298137ca74a744c1e6e22cfc0bf9dca3a2f41f51bc92eb05695155d905a",
+ "sha256:bc00d1210567a4cdd215ac6e17dc00cb9893ee521cee701adfd0fa43f7c73139",
+ "sha256:c1cb29b1fced01f97e6d5631c3edc2dadb424d1f4421dad079cb13fc97acb42f",
+ "sha256:c94dc64b1a389a416fc4218cd4799aa3756f25940cae33530a4f7f2f54f166da",
+ "sha256:ceaa28a5bce8a46a130cd223e895080e258a88d51bf6e8de2fc54a6ef7e38c34",
+ "sha256:cff6453e25204d3369c47b97dd34783ca820611bd334779d22192da23784194b",
+ "sha256:d0b64409df09edb4c365d95004775c988259efe9be39697d7315c42b7a5e7e94",
+ "sha256:d4813b30cb62d3b63ccc60dd12f2121780c7a3068db692daeb90f989877aaf04",
+ "sha256:da3c55cdc66cfc3fffb607db49a42448785ea2732f055ac1549b69dcb392663b",
+ "sha256:e058c7656c44fb494a11443191e381355388443d543f6fc1a245d5d238544396",
+ "sha256:fed0f22bf1313ff79c7fc318f7199d6c2f96d4de3234b2f12a1eab350e597c06",
+ "sha256:ffd4e4877a78c84d693e491b223385e0271278f5f4e1476a4962dca6824ecfeb"
+ ],
+ "index": "pypi",
+ "version": "==3.17.2"
},
"six": {
"hashes": [
- "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
- "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
+ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
+ "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
"index": "pypi",
- "version": "==1.14.0"
+ "version": "==1.15.0"
},
"sqlalchemy": {
"hashes": [
- "sha256:083e383a1dca8384d0ea6378bd182d83c600ed4ff4ec8247d3b2442cf70db1ad",
- "sha256:0a690a6486658d03cc6a73536d46e796b6570ac1f8a7ec133f9e28c448b69828",
- "sha256:114b6ace30001f056e944cebd46daef38fdb41ebb98f5e5940241a03ed6cad43",
- "sha256:128f6179325f7597a46403dde0bf148478f868df44841348dfc8d158e00db1f9",
- "sha256:13d48cd8b925b6893a4e59b2dfb3e59a5204fd8c98289aad353af78bd214db49",
- "sha256:211a1ce7e825f7142121144bac76f53ac28b12172716a710f4bf3eab477e730b",
- "sha256:2dc57ee80b76813759cccd1a7affedf9c4dbe5b065a91fb6092c9d8151d66078",
- "sha256:3e625e283eecc15aee5b1ef77203bfb542563fa4a9aa622c7643c7b55438ff49",
- "sha256:43078c7ec0457387c79b8d52fff90a7ad352ca4c7aa841c366238c3e2cf52fdf",
- "sha256:5b1bf3c2c2dca738235ce08079783ef04f1a7fc5b21cf24adaae77f2da4e73c3",
- "sha256:6056b671aeda3fc451382e52ab8a753c0d5f66ef2a5ccc8fa5ba7abd20988b4d",
- "sha256:68d78cf4a9dfade2e6cf57c4be19f7b82ed66e67dacf93b32bb390c9bed12749",
- "sha256:7025c639ce7e170db845e94006cf5f404e243e6fc00d6c86fa19e8ad8d411880",
- "sha256:7224e126c00b8178dfd227bc337ba5e754b197a3867d33b9f30dc0208f773d70",
- "sha256:7d98e0785c4cd7ae30b4a451416db71f5724a1839025544b4edbd92e00b91f0f",
- "sha256:8d8c21e9d4efef01351bf28513648ceb988031be4159745a7ad1b3e28c8ff68a",
- "sha256:bbb545da054e6297242a1bb1ba88e7a8ffb679f518258d66798ec712b82e4e07",
- "sha256:d00b393f05dbd4ecd65c989b7f5a81110eae4baea7a6a4cdd94c20a908d1456e",
- "sha256:e18752cecaef61031252ca72031d4d6247b3212ebb84748fc5d1a0d2029c23ea"
- ],
- "index": "pypi",
- "version": "==1.3.16"
+ "sha256:0942a3a0df3f6131580eddd26d99071b48cfe5aaf3eab2783076fbc5a1c1882e",
+ "sha256:0ec575db1b54909750332c2e335c2bb11257883914a03bc5a3306a4488ecc772",
+ "sha256:109581ccc8915001e8037b73c29590e78ce74be49ca0a3630a23831f9e3ed6c7",
+ "sha256:16593fd748944726540cd20f7e83afec816c2ac96b082e26ae226e8f7e9688cf",
+ "sha256:427273b08efc16a85aa2b39892817e78e3ed074fcb89b2a51c4979bae7e7ba98",
+ "sha256:50c4ee32f0e1581828843267d8de35c3298e86ceecd5e9017dc45788be70a864",
+ "sha256:512a85c3c8c3995cc91af3e90f38f460da5d3cade8dc3a229c8e0879037547c9",
+ "sha256:57aa843b783179ab72e863512e14bdcba186641daf69e4e3a5761d705dcc35b1",
+ "sha256:621f58cd921cd71ba6215c42954ffaa8a918eecd8c535d97befa1a8acad986dd",
+ "sha256:6ac2558631a81b85e7fb7a44e5035347938b0a73f5fdc27a8566777d0792a6a4",
+ "sha256:716754d0b5490bdcf68e1e4925edc02ac07209883314ad01a137642ddb2056f1",
+ "sha256:736d41cfebedecc6f159fc4ac0769dc89528a989471dc1d378ba07d29a60ba1c",
+ "sha256:8619b86cb68b185a778635be5b3e6018623c0761dde4df2f112896424aa27bd8",
+ "sha256:87fad64529cde4f1914a5b9c383628e1a8f9e3930304c09cf22c2ae118a1280e",
+ "sha256:89494df7f93b1836cae210c42864b292f9b31eeabca4810193761990dc689cce",
+ "sha256:8cac7bb373a5f1423e28de3fd5fc8063b9c8ffe8957dc1b1a59cb90453db6da1",
+ "sha256:8fd452dc3d49b3cc54483e033de6c006c304432e6f84b74d7b2c68afa2569ae5",
+ "sha256:adad60eea2c4c2a1875eb6305a0b6e61a83163f8e233586a4d6a55221ef984fe",
+ "sha256:c26f95e7609b821b5f08a72dab929baa0d685406b953efd7c89423a511d5c413",
+ "sha256:cbe1324ef52ff26ccde2cb84b8593c8bf930069dfc06c1e616f1bfd4e47f48a3",
+ "sha256:d05c4adae06bd0c7f696ae3ec8d993ed8ffcc4e11a76b1b35a5af8a099bd2284",
+ "sha256:d98bc827a1293ae767c8f2f18be3bb5151fd37ddcd7da2a5f9581baeeb7a3fa1",
+ "sha256:da2fb75f64792c1fc64c82313a00c728a7c301efe6a60b7a9fe35b16b4368ce7",
+ "sha256:e4624d7edb2576cd72bb83636cd71c8ce544d8e272f308bd80885056972ca299",
+ "sha256:e89e0d9e106f8a9180a4ca92a6adde60c58b1b0299e1b43bd5e0312f535fbf33",
+ "sha256:f11c2437fb5f812d020932119ba02d9e2bc29a6eca01a055233a8b449e3e1e7d",
+ "sha256:f57be5673e12763dd400fea568608700a63ce1c6bd5bdbc3cc3a2c5fdb045274",
+ "sha256:fc728ece3d5c772c196fd338a99798e7efac7a04f9cb6416299a3638ee9a94cd"
+ ],
+ "index": "pypi",
+ "version": "==1.3.18"
},
"subprocess32": {
"hashes": [
"sha256:88e37c1aac5388df41cc8a8456bb49ebffd321a3ad4d70358e3518176de3a56b",
+ "sha256:e45d985aef903c5b7444d34350b05da91a9e0ea015415ab45a21212786c649d0",
"sha256:eb2937c80497978d181efa1b839ec2d9622cf9600a039a79d0e108d1f9aec79d"
],
"index": "pypi",
@@ -2710,36 +2830,39 @@
},
"tensorboard": {
"hashes": [
- "sha256:9a2a2dc9856187679e93f3c95e5dc771dd47e3257db09767b4be118d734b4dc2"
+ "sha256:a3feb73e1221c0a512398ad2cd08570fb082d8a2ba364aa0562543ecbd3659ef"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==2.2.1"
+ "version": "==2.2.2"
},
"tensorboard-plugin-wit": {
"hashes": [
- "sha256:1fdf4ac343f1665453205aef8bb227b0204893bb5ffb792d2ed4509b1daf3d4f",
- "sha256:243f117d117f9e81a21dc64b602b2bcb256ca5ba038867b96022d02271b17106"
+ "sha256:ee775f04821185c90d9a0e9c56970ee43d7c41403beb6629385b39517129685b"
],
- "version": "==1.6.0.post3"
+ "version": "==1.7.0"
},
- "tensorflow-estimator": {
+ "tensorflow": {
"hashes": [
- "sha256:d09dacdd127f2579cea8d5af21f4a918036b8ae246adc82f26b61f91cc247dc2"
+ "sha256:267017724a49c367ca5df536e5f6d3d59643eaed946c82233d6b371e62b5ddc8",
+ "sha256:3ee8819732d8594913b7d22ded7b22e48a49aa015050d8dd8464eaa010ba2e41",
+ "sha256:572f69d2d0a3d3d83ebfb2c24e6d73d88b85a09f5da796974ef4a0ad83ff7cde",
+ "sha256:6735486ee9c3cb0807476e2b36ef7a4cd6c597cb24abf496e66b703360e1e54e",
+ "sha256:68ea22aee9c269a6a0c1061c141f1ec1cd1b1be7569390519c1bf4773f434a40",
+ "sha256:784ab8217e4b0eb4d121c28430c6cdc2ce56c02634a9720d84fb30598b338b8c",
+ "sha256:7ed67b47cdf6598a79583de5b57c595493eac2b8b6b3a828f912354716cb8149",
+ "sha256:8f364528f70d895b96a0de36c7c6002644bf4c5df1ee3fbfa775f5cee6571ad7",
+ "sha256:bbcfb04738099bd46822db91584db74703fdddacf4cd0a76acfc5e086956b5ba",
+ "sha256:c332c7fc5cfd54cb86d5da99787c9693e3a924848097c54df1b71ee595a39c93",
+ "sha256:dc5548562308acde7931f040e73d46ae31b398924cf675c3486fd3504e00a4af",
+ "sha256:f5f27528570fc0d7b90668be10c5dfd90d6ceb8fd2ed62d7d679554acb616bfe"
],
- "version": "==2.2.0"
+ "index": "pypi",
+ "version": "==2.2"
},
- "tensorflow-gpu": {
+ "tensorflow-estimator": {
"hashes": [
- "sha256:3cd3fa2b13a505902704a63d6b2f256cdc85ddfd6c70dc7093796b7e490d09c4",
- "sha256:453f0e3d8e56c47f4b374fba17cb5e0b57afbe34cd17f565b5498b5a0ccf33ac",
- "sha256:4c698dc157ba74aa69fc7bb41669f4f34f63f07bd722dd3b5aea33458a660066",
- "sha256:5853b595cf82f803d3dddc9b9c00996a514dcfc831d2f899f0bb8073795f6301",
- "sha256:845f261b0b922740bdd7f21fa3a4bed8ffd9e1712decd552fb33621da4d8ec45",
- "sha256:b706f0ed98d3c216ad65272c3a08a92f6fe7e38f57b54d3f9b5800043600e215",
- "sha256:ba1e16249cf9aa4057d0af443df493f8a1683be113703f6d7f184f144ac673e4",
- "sha256:f0b37fc5847987c1ca4f453273667497782a8920716a804f66247e0c095fef38"
+ "sha256:d09dacdd127f2579cea8d5af21f4a918036b8ae246adc82f26b61f91cc247dc2"
],
- "index": "pypi",
"version": "==2.2.0"
},
"termcolor": {
@@ -2765,19 +2888,18 @@
},
"tifffile": {
"hashes": [
- "sha256:2e110ea3a6381df534261a85091490a5678faa4535aa14cc11b8ea8379dcbf01",
- "sha256:abfce379f2b4b97759796c1489ea0e73c349fc71bf09bea2a5d076cbe7cfd4eb"
+ "sha256:73cd17d8df01fed38b9000c9b209eb7c894fde5abc616c5ff7b1f476e38cf07f",
+ "sha256:cd8549d6f0742c3c95a856744a26064a1aad1c132fbab95dc9e5dce891a62c17"
],
"markers": "python_version >= '3.6'",
- "version": "==2020.5.11"
+ "version": "==2020.7.24"
},
"toml": {
"hashes": [
- "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
- "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e",
- "sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"
+ "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f",
+ "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"
],
- "version": "==0.10.0"
+ "version": "==0.10.1"
},
"tornado": {
"hashes": [
@@ -2801,20 +2923,62 @@
],
"version": "==4.3.3"
},
+ "typed-ast": {
+ "hashes": [
+ "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
+ "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
+ "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
+ "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
+ "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
+ "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
+ "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
+ "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
+ "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
+ "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
+ "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
+ "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
+ "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
+ "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
+ "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
+ "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
+ "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
+ "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
+ "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
+ "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
+ "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
+ ],
+ "version": "==1.4.1"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:6e95524d8a547a91e08f404ae485bbb71962de46967e1b71a0cb89af24e761c5",
+ "sha256:79ee589a3caca649a9bfd2a8de4709837400dfa00b6cc81962a1e6a1815969ae",
+ "sha256:f8d2bd89d25bc39dabe7d23df520442fa1d8969b82544370e03d88b5a591c392"
+ ],
+ "version": "==3.7.4.2"
+ },
"urllib3": {
"hashes": [
- "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527",
- "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"
+ "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a",
+ "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"
],
"index": "pypi",
- "version": "==1.25.9"
+ "version": "==1.25.10"
+ },
+ "virtualenv": {
+ "hashes": [
+ "sha256:7b54fd606a1b85f83de49ad8d80dbec08e983a2d2f96685045b262ebc7481ee5",
+ "sha256:8cd7b2a4850b003a11be2fc213e206419efab41115cc14bca20e69654f2ac08e"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==20.0.30"
},
"wcwidth": {
"hashes": [
- "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1",
- "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"
+ "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784",
+ "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"
],
- "version": "==0.1.9"
+ "version": "==0.2.5"
},
"webencodings": {
"hashes": [
@@ -2854,26 +3018,26 @@
},
"yarl": {
"hashes": [
- "sha256:0c2ab325d33f1b824734b3ef51d4d54a54e0e7a23d13b86974507602334c2cce",
- "sha256:0ca2f395591bbd85ddd50a82eb1fde9c1066fafe888c5c7cc1d810cf03fd3cc6",
- "sha256:2098a4b4b9d75ee352807a95cdf5f10180db903bc5b7270715c6bbe2551f64ce",
- "sha256:25e66e5e2007c7a39541ca13b559cd8ebc2ad8fe00ea94a2aad28a9b1e44e5ae",
- "sha256:26d7c90cb04dee1665282a5d1a998defc1a9e012fdca0f33396f81508f49696d",
- "sha256:308b98b0c8cd1dfef1a0311dc5e38ae8f9b58349226aa0533f15a16717ad702f",
- "sha256:3ce3d4f7c6b69c4e4f0704b32eca8123b9c58ae91af740481aa57d7857b5e41b",
- "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b",
- "sha256:5b10eb0e7f044cf0b035112446b26a3a2946bca9d7d7edb5e54a2ad2f6652abb",
- "sha256:6faa19d3824c21bcbfdfce5171e193c8b4ddafdf0ac3f129ccf0cdfcb083e462",
- "sha256:944494be42fa630134bf907714d40207e646fd5a94423c90d5b514f7b0713fea",
- "sha256:a161de7e50224e8e3de6e184707476b5a989037dcb24292b391a3d66ff158e70",
- "sha256:a4844ebb2be14768f7994f2017f70aca39d658a96c786211be5ddbe1c68794c1",
- "sha256:c2b509ac3d4b988ae8769901c66345425e361d518aecbe4acbfc2567e416626a",
- "sha256:c9959d49a77b0e07559e579f38b2f3711c2b8716b8410b320bf9713013215a1b",
- "sha256:d8cdee92bc930d8b09d8bd2043cedd544d9c8bd7436a77678dd602467a993080",
- "sha256:e15199cdb423316e15f108f51249e44eb156ae5dba232cb73be555324a1d49c2"
+ "sha256:040b237f58ff7d800e6e0fd89c8439b841f777dd99b4a9cca04d6935564b9409",
+ "sha256:17668ec6722b1b7a3a05cc0167659f6c95b436d25a36c2d52db0eca7d3f72593",
+ "sha256:3a584b28086bc93c888a6c2aa5c92ed1ae20932f078c46509a66dce9ea5533f2",
+ "sha256:4439be27e4eee76c7632c2427ca5e73703151b22cae23e64adb243a9c2f565d8",
+ "sha256:48e918b05850fffb070a496d2b5f97fc31d15d94ca33d3d08a4f86e26d4e7c5d",
+ "sha256:9102b59e8337f9874638fcfc9ac3734a0cfadb100e47d55c20d0dc6087fb4692",
+ "sha256:9b930776c0ae0c691776f4d2891ebc5362af86f152dd0da463a6614074cb1b02",
+ "sha256:b3b9ad80f8b68519cc3372a6ca85ae02cc5a8807723ac366b53c0f089db19e4a",
+ "sha256:bc2f976c0e918659f723401c4f834deb8a8e7798a71be4382e024bcc3f7e23a8",
+ "sha256:c22c75b5f394f3d47105045ea551e08a3e804dc7e01b37800ca35b58f856c3d6",
+ "sha256:c52ce2883dc193824989a9b97a76ca86ecd1fa7955b14f87bf367a61b6232511",
+ "sha256:ce584af5de8830d8701b8979b18fcf450cef9a382b1a3c8ef189bedc408faf1e",
+ "sha256:da456eeec17fa8aa4594d9a9f27c0b1060b6a75f2419fe0c00609587b2695f4a",
+ "sha256:db6db0f45d2c63ddb1a9d18d1b9b22f308e52c83638c26b422d520a815c4b3fb",
+ "sha256:df89642981b94e7db5596818499c4b2219028f2a528c9c37cc1de45bf2fd3a3f",
+ "sha256:f18d68f2be6bf0e89f1521af2b1bb46e66ab0018faafa81d70f358153170a317",
+ "sha256:f379b7f83f23fe12823085cd6b906edc49df969eb99757f58ff382349a3303c6"
],
"markers": "python_version >= '3.5'",
- "version": "==1.4.2"
+ "version": "==1.5.1"
}
}
}
diff --git a/README.md b/README.md
index 1d2e08de02..f78a070883 100644
--- a/README.md
+++ b/README.md
@@ -66,8 +66,8 @@ Supported Cars
| ----------| ------------------------------| ------------------| -----------------| -------------------| ------------------|
| Acura | ILX 2016-18 | AcuraWatch Plus | openpilot | 25mph1 | 25mph |
| Acura | RDX 2016-18 | AcuraWatch Plus | openpilot | 25mph1 | 12mph |
-| Honda | Accord 2018-19 | All | Stock | 0mph | 3mph |
-| Honda | Accord Hybrid 2018-19 | All | Stock | 0mph | 3mph |
+| Honda | Accord 2018-20 | All | Stock | 0mph | 3mph |
+| Honda | Accord Hybrid 2018-20 | All | Stock | 0mph | 3mph |
| Honda | Civic Hatchback 2017-19 | Honda Sensing | Stock | 0mph | 12mph |
| Honda | Civic Sedan/Coupe 2016-18 | Honda Sensing | openpilot | 0mph | 12mph |
| Honda | Civic Sedan/Coupe 2019-20 | Honda Sensing | Stock | 0mph | 2mph2 |
@@ -76,12 +76,13 @@ Supported Cars
| Honda | CR-V Hybrid 2017-2019 | Honda Sensing | Stock | 0mph | 12mph |
| Honda | Fit 2018-19 | Honda Sensing | openpilot | 25mph1 | 12mph |
| Honda | HR-V 2019 | Honda Sensing | openpilot | 25mph1 | 12mph |
-| Honda | Insight 2019 | Honda Sensing | Stock | 0mph | 3mph |
+| Honda | Insight 2019-20 | Honda Sensing | Stock | 0mph | 3mph |
| Honda | Odyssey 2018-20 | Honda Sensing | openpilot | 25mph1 | 0mph |
| Honda | Passport 2019 | All | openpilot | 25mph1 | 12mph |
| Honda | Pilot 2016-18 | Honda Sensing | openpilot | 25mph1 | 12mph |
| Honda | Pilot 2019 | All | openpilot | 25mph1 | 12mph |
| Honda | Ridgeline 2017-20 | Honda Sensing | openpilot | 25mph1 | 12mph |
+| Hyundai | Sonata 2020 | All | Stock | 0mph | 0mph |
| Lexus | CT Hybrid 2017-18 | All | Stock3| 0mph | 0mph |
| Lexus | ES 2019 | All | openpilot | 0mph | 0mph |
| Lexus | ES Hybrid 2019 | All | openpilot | 0mph | 0mph |
@@ -91,6 +92,7 @@ Supported Cars
| Lexus | RX 2016-17 | All | Stock3| 0mph | 0mph |
| Lexus | RX 2020 | All | openpilot | 0mph | 0mph |
| Lexus | RX Hybrid 2016-19 | All | Stock3| 0mph | 0mph |
+| Lexus | RX Hybrid 2020 | All | openpilot | 0mph | 0mph |
| Toyota | Avalon 2016 | TSS-P | Stock3| 20mph1 | 0mph |
| Toyota | Avalon 2017-18 | All | Stock3| 20mph1 | 0mph |
| Toyota | Camry 2018-20 | All | Stock | 0mph4 | 0mph |
@@ -106,7 +108,7 @@ Supported Cars
| Toyota | Highlander 2020 | All | openpilot | 0mph | 0mph |
| Toyota | Highlander Hybrid 2020 | All | openpilot | 0mph | 0mph |
| Toyota | Prius 2016 | TSS-P | Stock3| 0mph | 0mph |
-| Toyota | Prius 2017-19 | All | Stock3| 0mph | 0mph |
+| Toyota | Prius 2017-20 | All | Stock3| 0mph | 0mph |
| Toyota | Prius Prime 2017-20 | All | Stock3| 0mph | 0mph |
| Toyota | Rav4 2016 | TSS-P | Stock3| 20mph1 | 0mph |
| Toyota | Rav4 2017-18 | All | Stock3| 20mph1 | 0mph |
@@ -116,9 +118,9 @@ Supported Cars
| Toyota | Rav4 Hybrid 2019-20 | All | openpilot | 0mph | 0mph |
| Toyota | Sienna 2018-20 | All | Stock3| 0mph | 0mph |
-1[Comma Pedal](https://community.comma.ai/wiki/index.php/Comma_Pedal) is used to provide stop-and-go capability to some of the openpilot-supported cars that don't currently support stop-and-go. Here is how to [build a Comma Pedal](https://medium.com/@jfrux/comma-pedal-building-with-macrofab-6328bea791e8). ***NOTE: The Comma Pedal is not officially supported by [comma](https://comma.ai).***
+1[Comma Pedal](https://github.com/commaai/openpilot/wiki/comma-pedal) is used to provide stop-and-go capability to some of the openpilot-supported cars that don't currently support stop-and-go. ***NOTE: The Comma Pedal is not officially supported by [comma](https://comma.ai).***
22019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph.
-3When disconnecting the Driver Support Unit (DSU), openpilot ACC will replace stock ACC. For DSU locations, see [Toyota Wiki page](https://community.comma.ai/wiki/index.php/Toyota). ***NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).***
+3When disconnecting the Driver Support Unit (DSU), openpilot ACC will replace stock ACC. ***NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).***
428mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control.
Community Maintained Cars and Features
@@ -134,35 +136,39 @@ Community Maintained Cars and Features
| Chrysler | Pacifica 2020 | Adaptive Cruise | Stock | 0mph | 39mph |
| Chrysler | Pacifica Hybrid 2017-18 | Adaptive Cruise | Stock | 0mph | 9mph |
| Chrysler | Pacifica Hybrid 2019-20 | Adaptive Cruise | Stock | 0mph | 39mph |
-| Genesis | G80 20182 | All | Stock | 0mph | 0mph |
-| Genesis | G90 20182 | All | Stock | 0mph | 0mph |
-| GMC | Acadia Denali 20183| Adaptive Cruise | openpilot | 0mph | 7mph |
+| Genesis | G70 2018 | All | Stock | 0mph | 0mph |
+| Genesis | G80 2018 | All | Stock | 0mph | 0mph |
+| Genesis | G90 2018 | All | Stock | 0mph | 0mph |
+| GMC | Acadia Denali 20182| Adaptive Cruise | openpilot | 0mph | 7mph |
| Holden | Astra 20171 | Adaptive Cruise | openpilot | 0mph | 7mph |
-| Hyundai | Elantra 2017-192 | SCC + LKAS | Stock | 19mph | 34mph |
-| Hyundai | Genesis 2015-162 | SCC + LKAS | Stock | 19mph | 37mph |
-| Hyundai | Ioniq 20172 | SCC + LKAS | Stock | 0mph | 32mph |
-| Hyundai | Ioniq 2019 EV2 | SCC + LKAS | Stock | 0mph | 32mph |
-| Hyundai | Kona 2017-192 | SCC + LKAS | Stock | 22mph | 0mph |
-| Hyundai | Kona 2019 EV2 | SCC + LKAS | Stock | 0mph | 0mph |
-| Hyundai | Palisade 20202 | All | Stock | 0mph | 0mph |
-| Hyundai | Santa Fe 20192 | All | Stock | 0mph | 0mph |
-| Hyundai | Sonata 20202 | All | Stock | 0mph | 0mph |
+| Hyundai | Elantra 2017-19 | SCC + LKAS | Stock | 19mph | 34mph |
+| Hyundai | Genesis 2015-16 | SCC + LKAS | Stock | 19mph | 37mph |
+| Hyundai | Ioniq Electric Premium SE 2020| SCC + LKAS | Stock | 0mph | 32mph |
+| Hyundai | Ioniq Electric Limited 2019 | SCC + LKAS | Stock | 0mph | 32mph |
+| Hyundai | Kona 2020 | SCC + LKAS | Stock | 0mph | 0mph |
+| Hyundai | Kona EV 2019 | SCC + LKAS | Stock | 0mph | 0mph |
+| Hyundai | Palisade 2020 | All | Stock | 0mph | 0mph |
+| Hyundai | Santa Fe 2019 | All | Stock | 0mph | 0mph |
+| Hyundai | Sonata 2019 | All | Stock | 0mph | 0mph |
+| Hyundai | Veloster 2019 | SCC + LKAS | Stock | 5mph | 0mph |
| Jeep | Grand Cherokee 2016-18 | Adaptive Cruise | Stock | 0mph | 9mph |
-| Jeep | Grand Cherokee 2019 | Adaptive Cruise | Stock | 0mph | 39mph |
-| Kia | Forte 20182 | SCC + LKAS | Stock | 0mph | 0mph |
-| Kia | Optima 20172 | SCC + LKAS/LDWS | Stock | 0mph | 32mph |
-| Kia | Optima 20192 | SCC + LKAS | Stock | 0mph | 0mph |
-| Kia | Sorento 20182 | SCC + LKAS | Stock | 0mph | 0mph |
-| Kia | Stinger 20182 | SCC + LKAS | Stock | 0mph | 0mph |
-| Nissan | Leaf 2019 | Propilot | Stock | 0mph | 0mph |
-| Nissan | X-Trail 2018 | Propilot | Stock | 0mph | 0mph |
+| Jeep | Grand Cherokee 2019-20 | Adaptive Cruise | Stock | 0mph | 39mph |
+| Kia | Forte 2018-19 | SCC + LKAS | Stock | 0mph | 0mph |
+| Kia | Optima 2017 | SCC + LKAS/LDWS | Stock | 0mph | 32mph |
+| Kia | Optima 2019 | SCC + LKAS | Stock | 0mph | 0mph |
+| Kia | Sorento 2018 | SCC + LKAS | Stock | 0mph | 0mph |
+| Kia | Stinger 2018 | SCC + LKAS | Stock | 0mph | 0mph |
+| Nissan | Leaf 2018-19 | Propilot | Stock | 0mph | 0mph |
+| Nissan | Rogue 2019 | Propilot | Stock | 0mph | 0mph |
+| Nissan | X-Trail 2017 | Propilot | Stock | 0mph | 0mph |
+| Subaru | Ascent 2019 | EyeSight | Stock | 0mph | 0mph |
| Subaru | Crosstrek 2018-19 | EyeSight | Stock | 0mph | 0mph |
-| Subaru | Impreza 2018-20 | EyeSight | Stock | 0mph | 0mph |
-| Volkswagen| Golf 2016-193 | Driver Assistance | Stock | 0mph | 0mph |
+| Subaru | Forester 2019 | EyeSight | Stock | 0mph | 0mph |
+| Subaru | Impreza 2017-19 | EyeSight | Stock | 0mph | 0mph |
+| Volkswagen| Golf 2015-19 | Driver Assistance | Stock | 0mph | 0mph |
-1Requires a [panda](https://comma.ai/shop/products/panda-obd-ii-dongle) and [community built giraffe](https://zoneos.com/volt/). ***NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).***
-2Requires a [panda](https://comma.ai/shop/products/panda-obd-ii-dongle) and open sourced [Hyundai giraffe](https://github.com/commaai/neo/tree/master/giraffe/hyundai), designed for the 2019 Sante Fe; pinout may differ for other Hyundai and Kia models.
-3Requires a [custom connector](https://community.comma.ai/wiki/index.php/Volkswagen#Integration_at_R242_Camera) for the [car harness](https://comma.ai/shop/products/car-harness)
+1Requires an [OBD-II car harness](https://comma.ai/shop/products/comma-car-harness) and [community built giraffe](https://github.com/commaai/openpilot/wiki/GM). ***NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).***
+2Requires a custom connector for the developer [car harness](https://comma.ai/shop/products/car-harness)
Although it's not upstream, there's a community of people getting openpilot to run on Tesla's [here](https://tinkla.us/)
@@ -175,7 +181,7 @@ Installation Instructions
Install openpilot on an EON or comma two by entering ``https://openpilot.comma.ai`` during the installer setup.
-Follow these [video instructions](https://youtu.be/3nlkomHathI) to properly mount the device on the windshield. Note: openpilot features an automatic pose calibration routine and openpilot performance should not be affected by small pitch and yaw misalignments caused by imprecise device mounting.
+Follow these [video instructions](https://youtu.be/lcjqxCymins) to properly mount the device on the windshield. Note: openpilot features an automatic pose calibration routine and openpilot performance should not be affected by small pitch and yaw misalignments caused by imprecise device mounting.
Before placing the device on your windshield, check the state and local laws and ordinances where you drive. Some state laws prohibit or restrict the placement of objects on the windshield of a motor vehicle.
@@ -278,7 +284,7 @@ openpilot is developed by [comma](https://comma.ai/) and by users like you. We w
You can add support for your car by following guides we have written for [Brand](https://medium.com/@comma_ai/how-to-write-a-car-port-for-openpilot-7ce0785eda84) and [Model](https://medium.com/@comma_ai/openpilot-port-guide-for-toyota-models-e5467f4b5fe6) ports. Generally, a car with adaptive cruise control and lane keep assist is a good candidate. [Join our Discord](https://discord.comma.ai) to discuss car ports: most car makes have a dedicated channel.
-Want to get paid to work on openpilot? [comma is hiring](https://comma.ai/jobs/). We also have a [bounty program](https://comma.ai/bounties.html).
+Want to get paid to work on openpilot? [comma is hiring](https://comma.ai/jobs/).
And [follow us on Twitter](https://twitter.com/comma_ai).
@@ -328,6 +334,7 @@ NO WARRANTY EXPRESSED OR IMPLIED.**
+[](https://github.com/commaai/openpilot/actions)
[](https://lgtm.com/projects/g/commaai/openpilot/alerts/)
[](https://lgtm.com/projects/g/commaai/openpilot/context:python)
[](https://lgtm.com/projects/g/commaai/openpilot/context:cpp)
diff --git a/RELEASES.md b/RELEASES.md
index 67beec7795..3709d0f222 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,40 @@
+Version 0.7.9 (2020-XX-XX)
+========================
+ * Improved car battery power management
+
+Version 0.7.8 (2020-08-19)
+========================
+ * New driver monitoring model: improved face detection and better compatibility with sunglasses
+ * Download NEOS operating system updates in the background
+ * Improved updater reliability and responsiveness
+ * Hyundai Kona 2020, Veloster 2019, and Genesis G70 2018 support thanks to xps-genesis!
+
+Version 0.7.7 (2020-07-20)
+========================
+ * White panda is no longer supported, upgrade to comma two or black panda
+ * Improved vehicle model estimation using high precision localizer
+ * Improved thermal management on comma two
+ * Improved autofocus for road-facing camera
+ * Improved noise performance for driver-facing camera
+ * Block lane change start using blindspot monitor on select Toyota, Hyundai, and Subaru
+ * Fix GM ignition detection
+ * Code cleanup and smaller release sizes
+ * Hyundai Sonata 2020 promoted to officially supported car
+ * Hyundai Ioniq Electric Limited 2019 and Ioniq SE 2020 support thanks to baldwalker!
+ * Subaru Forester 2019 and Ascent 2019 support thanks to martinl!
+
+Version 0.7.6.1 (2020-06-16)
+========================
+* Hotfix: update kernel on some comma twos (orders #8570-#8680)
+
+Version 0.7.6 (2020-06-05)
+========================
+* White panda is deprecated, upgrade to comma two or black panda
+* 2017 Nissan X-Trail, 2018-19 Leaf and 2019 Rogue support thanks to avolmensky!
+* 2017 Mazda CX-5 support in dashcam mode thanks to Jafaral!
+* Huge CPU savings in modeld by using thneed!
+* Lots of code cleanup and refactors
+
Version 0.7.5 (2020-05-13)
========================
* Right-Hand Drive support for both driving and driver monitoring!
@@ -5,7 +42,6 @@ Version 0.7.5 (2020-05-13)
* New driver monitoring model: overall improvement on comma two
* Driver camera preview in settings to improve mounting position
* Added support for many Hyundai, Kia, Genesis models thanks to xx979xx!
-* 2019 Nissan X-Trail and 2018 Nissan Leaf support thanks to avolmensky!
* Improved lateral tuning for 2020 Toyota Rav 4 (hybrid)
Version 0.7.4 (2020-03-20)
diff --git a/SAFETY.md b/SAFETY.md
index 5a3c287fe9..9cf8933b93 100644
--- a/SAFETY.md
+++ b/SAFETY.md
@@ -1,7 +1,7 @@
openpilot Safety
======
-openpilot is an Adaptive Cruise Control (ACC) and Automated Lane Centering (ALC) system.
+openpilot is an Adaptive Cruise Control (ACC) and Automated Lane Centering (ALC) system.
Like other ACC and ALC systems, openpilot is a failsafe passive system and it requires the
driver to be alert and to pay attention at all times.
@@ -22,7 +22,7 @@ hardware-in-the-loop and in-vehicle tests before each software release.
Following Hazard and Risk Analysis and FMEA, at a very high level, we have designed openpilot
ensuring two main safety requirements.
-1. The driver must always be capable to immediately retake manual control of the vehicle,
+1. The driver must always be capable to immediately retake manual control of the vehicle,
by stepping on either pedal or by pressing the cancel button.
2. The vehicle must not alter its trajectory too quickly for the driver to safely
react. This means that while the system is engaged, the actuators are constrained
diff --git a/SConstruct b/SConstruct
index 3ba359a4fc..e3765a15c1 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1,4 +1,7 @@
+import Cython
+import distutils
import os
+import shutil
import subprocess
import sys
import platform
@@ -11,6 +14,10 @@ AddOption('--asan',
action='store_true',
help='turn on ASAN')
+# Rebuild cython extensions if python, distutils, or cython change
+cython_dependencies = [Value(v) for v in (sys.version, distutils.__version__, Cython.__version__)]
+Export('cython_dependencies')
+
arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
if platform.system() == "Darwin":
arch = "Darwin"
@@ -18,6 +25,7 @@ if arch == "aarch64" and not os.path.isdir("/system"):
arch = "larch64"
webcam = bool(ARGUMENTS.get("use_webcam", 0))
+QCOM_REPLAY = arch == "aarch64" and os.getenv("QCOM_REPLAY") is not None
if arch == "aarch64" or arch == "larch64":
lenv = {
@@ -43,20 +51,31 @@ if arch == "aarch64" or arch == "larch64":
]
if arch == "larch64":
- libpath += ["#phonelibs/snpe/larch64"]
- libpath += ["#phonelibs/libyuv/larch64/lib"]
- libpath += ["/usr/lib/aarch64-linux-gnu"]
+ libpath += [
+ "#phonelibs/snpe/larch64",
+ "#phonelibs/libyuv/larch64/lib",
+ "/usr/lib/aarch64-linux-gnu"
+ ]
cflags = ["-DQCOM2", "-mcpu=cortex-a57"]
cxxflags = ["-DQCOM2", "-mcpu=cortex-a57"]
rpath = ["/usr/local/lib"]
else:
- libpath += ["#phonelibs/snpe/aarch64"]
- libpath += ["#phonelibs/libyuv/lib"]
+ libpath += [
+ "#phonelibs/snpe/aarch64",
+ "#phonelibs/libyuv/lib"
+ ]
cflags = ["-DQCOM", "-mcpu=cortex-a57"]
cxxflags = ["-DQCOM", "-mcpu=cortex-a57"]
rpath = ["/system/vendor/lib64"]
+ if QCOM_REPLAY:
+ cflags += ["-DQCOM_REPLAY"]
+ cxxflags += ["-DQCOM_REPLAY"]
+
else:
+ cflags = []
+ cxxflags = []
+
lenv = {
"PATH": "#external/bin:" + os.environ['PATH'],
}
@@ -72,6 +91,8 @@ else:
"/usr/local/lib",
"/System/Library/Frameworks/OpenGL.framework/Libraries",
]
+ cflags += ["-DGL_SILENCE_DEPRECATION"]
+ cxxflags += ["-DGL_SILENCE_DEPRECATION"]
else:
libpath = [
"#phonelibs/snpe/x86_64-linux-clang",
@@ -84,18 +105,20 @@ else:
]
rpath = [
- "external/tensorflow/lib",
- "cereal",
- "selfdrive/common"]
+ "external/tensorflow/lib",
+ "cereal",
+ "selfdrive/common"
+ ]
# allows shared libraries to work globally
rpath = [os.path.join(os.getcwd(), x) for x in rpath]
- cflags = []
- cxxflags = []
-
-ccflags_asan = ["-fsanitize=address", "-fno-omit-frame-pointer"] if GetOption('asan') else []
-ldflags_asan = ["-fsanitize=address"] if GetOption('asan') else []
+if GetOption('asan'):
+ ccflags_asan = ["-fsanitize=address", "-fno-omit-frame-pointer"]
+ ldflags_asan = ["-fsanitize=address"]
+else:
+ ccflags_asan = []
+ ldflags_asan = []
# change pythonpath to this
lenv["PYTHONPATH"] = Dir("#").path
@@ -106,11 +129,10 @@ env = Environment(
"-g",
"-fPIC",
"-O2",
- "-Werror=implicit-function-declaration",
- "-Werror=incompatible-pointer-types",
- "-Werror=int-conversion",
- "-Werror=return-type",
- "-Werror=format-extra-args",
+ "-Wunused",
+ "-Werror",
+ "-Wno-deprecated-register",
+ "-Wno-inconsistent-missing-override",
] + cflags + ccflags_asan,
CPPPATH=cpppath + [
@@ -134,6 +156,7 @@ env = Environment(
"#selfdrive/camerad/include",
"#selfdrive/loggerd/include",
"#selfdrive/modeld",
+ "#selfdrive/ui",
"#cereal/messaging",
"#cereal",
"#opendbc/can",
@@ -147,16 +170,73 @@ env = Environment(
CFLAGS=["-std=gnu11"] + cflags,
CXXFLAGS=["-std=c++14"] + cxxflags,
- LIBPATH=libpath +
- [
+ LIBPATH=libpath + [
"#cereal",
"#selfdrive/common",
"#phonelibs",
]
)
+qt_env = None
+if arch in ["x86_64", "Darwin", "larch64"]:
+ qt_env = env.Clone()
+
+ if arch == "larch64":
+ qt_env['QTDIR'] = "/usr/local/Qt-5.15.0"
+ QT_BASE = "/usr/local/Qt-5.15.0/"
+ qt_dirs = [
+ QT_BASE + "include/",
+ QT_BASE + "include/QtWidgets",
+ QT_BASE + "include/QtGui",
+ QT_BASE + "include/QtCore",
+ QT_BASE + "include/QtDBus",
+ ]
+ qt_env["RPATH"] += [QT_BASE + "lib"]
+ elif arch == "Darwin":
+ qt_env['QTDIR'] = "/usr/local/opt/qt"
+ QT_BASE = "/usr/local/opt/qt/"
+ qt_dirs = [
+ QT_BASE + "include/",
+ QT_BASE + "include/QtWidgets",
+ QT_BASE + "include/QtGui",
+ QT_BASE + "include/QtCore",
+ QT_BASE + "include/QtDBus",
+ ]
+ qt_env["LINKFLAGS"] += ["-F" + QT_BASE + "lib"]
+ else:
+ qt_dirs = [
+ f"/usr/include/{arch}-linux-gnu/qt5",
+ f"/usr/include/{arch}-linux-gnu/qt5/QtWidgets",
+ f"/usr/include/{arch}-linux-gnu/qt5/QtGui",
+ f"/usr/include/{arch}-linux-gnu/qt5/QtCore",
+ f"/usr/include/{arch}-linux-gnu/qt5/QtDBus",
+ ]
+
+ qt_env.Tool('qt')
+ qt_env['CPPPATH'] += qt_dirs
+ qt_flags = [
+ "-D_REENTRANT",
+ "-DQT_NO_DEBUG",
+ "-DQT_WIDGETS_LIB",
+ "-DQT_GUI_LIB",
+ "-DQT_CORE_LIB"
+ ]
+ qt_env['CXXFLAGS'] += qt_flags
+
if os.environ.get('SCONS_CACHE'):
- CacheDir('/tmp/scons_cache')
+ cache_dir = '/tmp/scons_cache'
+
+ if os.getenv('CI'):
+ branch = os.getenv('GIT_BRANCH')
+
+ if QCOM_REPLAY:
+ cache_dir = '/tmp/scons_cache_qcom_replay'
+ elif branch is not None and branch != 'master':
+ cache_dir_branch = '/tmp/scons_cache_' + branch
+ if not os.path.isdir(cache_dir_branch) and os.path.isdir(cache_dir):
+ shutil.copytree(cache_dir, cache_dir_branch)
+ cache_dir = cache_dir_branch
+ CacheDir(cache_dir)
node_interval = 5
node_count = 0
@@ -181,7 +261,7 @@ def abspath(x):
# still needed for apks
zmq = 'zmq'
-Export('env', 'arch', 'zmq', 'SHARED', 'webcam')
+Export('env', 'qt_env', 'arch', 'zmq', 'SHARED', 'webcam', 'QCOM_REPLAY')
# cereal and messaging are shared with the system
SConscript(['cereal/SConscript'])
@@ -209,11 +289,11 @@ SConscript(['opendbc/can/SConscript'])
SConscript(['common/SConscript'])
SConscript(['common/kalman/SConscript'])
+SConscript(['common/transformations/SConscript'])
SConscript(['phonelibs/SConscript'])
-if arch != "Darwin":
- SConscript(['selfdrive/camerad/SConscript'])
- SConscript(['selfdrive/modeld/SConscript'])
+SConscript(['selfdrive/camerad/SConscript'])
+SConscript(['selfdrive/modeld/SConscript'])
SConscript(['selfdrive/controls/lib/cluster/SConscript'])
SConscript(['selfdrive/controls/lib/lateral_mpc/SConscript'])
@@ -223,15 +303,18 @@ SConscript(['selfdrive/controls/lib/longitudinal_mpc_model/SConscript'])
SConscript(['selfdrive/boardd/SConscript'])
SConscript(['selfdrive/proclogd/SConscript'])
-#SConscript(['selfdrive/ui/SConscript'])
SConscript(['selfdrive/loggerd/SConscript'])
SConscript(['selfdrive/locationd/SConscript'])
SConscript(['selfdrive/locationd/models/SConscript'])
+
if arch == "aarch64":
SConscript(['selfdrive/logcatd/SConscript'])
SConscript(['selfdrive/sensord/SConscript'])
SConscript(['selfdrive/clocksd/SConscript'])
else:
SConscript(['tools/lib/index_log/SConscript'])
+
+if arch != "larch64":
+ SConscript(['selfdrive/ui/SConscript'])
diff --git a/apk/ai.comma.plus.offroad.apk b/apk/ai.comma.plus.offroad.apk
index 8a59c2b227..75f3b219b6 100644
--- a/apk/ai.comma.plus.offroad.apk
+++ b/apk/ai.comma.plus.offroad.apk
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d7b79038dccaa97d84bd38544573d3a52929770b76a259b25a27311464230e22
-size 13732809
+oid sha256:a198491887ed6029bffdf7f4dc28c4f9a6ba5f9d2235710fc11a1378893491d7
+size 13702777
diff --git a/apks b/apks
deleted file mode 160000
index f5d2c1715c..0000000000
--- a/apks
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit f5d2c1715c9482d898062110ce4c612093aa5d4f
diff --git a/common/SConscript b/common/SConscript
index 103d416f53..35abeb9ee4 100644
--- a/common/SConscript
+++ b/common/SConscript
@@ -1,6 +1,6 @@
-Import('env')
+Import('env', 'cython_dependencies')
-# parser
-env.Command(['common_pyx.so'],
- ['common_pyx_setup.py', 'clock.pyx'],
- "cd common && python3 common_pyx_setup.py build_ext --inplace")
+# Build cython clock module
+env.Command(['common_pyx.so', 'clock.cpp'],
+ cython_dependencies + ['common_pyx_setup.py', 'clock.pyx'],
+ "cd common && python3 common_pyx_setup.py build_ext --inplace")
diff --git a/common/android.py b/common/android.py
index 4342a4259a..43bb0f3c1e 100644
--- a/common/android.py
+++ b/common/android.py
@@ -12,6 +12,10 @@ NetworkStrength = log.ThermalData.NetworkStrength
ANDROID = os.path.isfile('/EON')
+def get_sound_card_online():
+ return (os.path.isfile('/proc/asound/card0/state') and
+ open('/proc/asound/card0/state').read().strip() == 'ONLINE')
+
def getprop(key):
if not ANDROID:
return ""
@@ -22,10 +26,10 @@ def get_imei(slot):
if slot not in ("0", "1"):
raise ValueError("SIM slot must be 0 or 1")
- ret = parse_service_call_string(service_call(["iphonesubinfo", "3" ,"i32", str(slot)]))
+ ret = parse_service_call_string(service_call(["iphonesubinfo", "3" , "i32", str(slot)]))
if not ret:
# allow non android to be identified differently
- ret = "%015d" % random.randint(0, 1<<32)
+ ret = "%015d" % random.randint(0, 1 << 32)
return ret
def get_serial():
@@ -47,10 +51,10 @@ def reboot(reason=None):
reason_args = ["s16", reason]
subprocess.check_output([
- "service", "call", "power", "16", # IPowerManager.reboot
- "i32", "0", # no confirmation,
+ "service", "call", "power", "16", # IPowerManager.reboot
+ "i32", "0", # no confirmation,
*reason_args,
- "i32", "1" # wait
+ "i32", "1" # wait
])
def service_call(call):
@@ -71,7 +75,7 @@ def parse_service_call_unpack(r, fmt):
def parse_service_call_string(r):
try:
- r = r[8:] # Cut off length field
+ r = r[8:] # Cut off length field
r = r.decode('utf_16_be')
# All pairs of two characters seem to be swapped. Not sure why
@@ -132,6 +136,7 @@ def get_network_type():
def get_network_strength(network_type):
network_strength = NetworkStrength.unknown
+
# from SignalStrength.java
def get_lte_level(rsrp, rssnr):
INT_MAX = 2147483647
diff --git a/common/api/__init__.py b/common/api/__init__.py
index 38fe6b2477..b030c33334 100644
--- a/common/api/__init__.py
+++ b/common/api/__init__.py
@@ -38,5 +38,4 @@ def api_get(endpoint, method='GET', timeout=None, access_token=None, **params):
headers['User-Agent'] = "openpilot-" + version
- return requests.request(method, backend+endpoint, timeout=timeout, headers = headers, params=params)
-
+ return requests.request(method, backend+endpoint, timeout=timeout, headers=headers, params=params)
diff --git a/common/apk.py b/common/apk.py
index 5716ed452a..c04c19aa5f 100644
--- a/common/apk.py
+++ b/common/apk.py
@@ -13,7 +13,7 @@ def get_installed_apks():
ret = {}
for x in dat:
if x.startswith("package:"):
- v,k = x.split("package:")[1].split("=")
+ v, k = x.split("package:")[1].split("=")
ret[k] = v
return ret
diff --git a/common/basedir.py b/common/basedir.py
index e928ded4c4..4d62fdc19c 100644
--- a/common/basedir.py
+++ b/common/basedir.py
@@ -8,4 +8,3 @@ if ANDROID:
else:
PERSIST = os.path.join(BASEDIR, "persist")
PARAMS = os.path.join(BASEDIR, "persist", "params")
-
diff --git a/common/compat.py b/common/compat.py
deleted file mode 100644
index 369f5e2d84..0000000000
--- a/common/compat.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# py2,3 compatiblity helpers
-
-basestring = (str, bytes)
diff --git a/common/file_helpers.py b/common/file_helpers.py
index 40c89fab0e..c7a70ab879 100644
--- a/common/file_helpers.py
+++ b/common/file_helpers.py
@@ -3,13 +3,17 @@ import shutil
import tempfile
from atomicwrites import AtomicWriter
+
def mkdirs_exists_ok(path):
+ if path.startswith('http://') or path.startswith('https://'):
+ raise ValueError('URL path')
try:
os.makedirs(path)
except OSError:
if not os.path.isdir(path):
raise
+
def rm_not_exists_ok(path):
try:
os.remove(path)
@@ -17,12 +21,14 @@ def rm_not_exists_ok(path):
if os.path.exists(path):
raise
+
def rm_tree_or_link(path):
if os.path.islink(path):
os.unlink(path)
elif os.path.isdir(path):
shutil.rmtree(path)
+
def get_tmpdir_on_same_filesystem(path):
normpath = os.path.normpath(path)
parts = normpath.split("/")
@@ -32,6 +38,7 @@ def get_tmpdir_on_same_filesystem(path):
return "/{}/runner/tmp".format(parts[1])
return "/tmp"
+
class AutoMoveTempdir():
def __init__(self, target_path, temp_dir=None):
self._target_path = target_path
@@ -44,14 +51,16 @@ class AutoMoveTempdir():
def close(self):
os.rename(self._path, self._target_path)
- def __enter__(self): return self
+ def __enter__(self):
+ return self
- def __exit__(self, type, value, traceback):
- if type is None:
+ def __exit__(self, exc_type, exc_value, traceback):
+ if exc_type is None:
self.close()
else:
shutil.rmtree(self._path)
+
class NamedTemporaryDir():
def __init__(self, temp_dir=None):
self._path = tempfile.mkdtemp(dir=temp_dir)
@@ -63,11 +72,13 @@ class NamedTemporaryDir():
def close(self):
shutil.rmtree(self._path)
- def __enter__(self): return self
+ def __enter__(self):
+ return self
- def __exit__(self, type, value, traceback):
+ def __exit__(self, exc_type, exc_value, traceback):
self.close()
+
def _get_fileobject_func(writer, temp_dir):
def _get_fileobject():
file_obj = writer.get_fileobject(dir=temp_dir)
@@ -75,6 +86,7 @@ def _get_fileobject_func(writer, temp_dir):
return file_obj
return _get_fileobject
+
def atomic_write_on_fs_tmp(path, **kwargs):
"""Creates an atomic writer using a temporary file in a temporary directory
on the same filesystem as path.
@@ -92,6 +104,7 @@ def atomic_write_in_dir(path, **kwargs):
writer = AtomicWriter(path, **kwargs)
return writer._open(_get_fileobject_func(writer, os.path.dirname(path)))
+
def atomic_write_in_dir_neos(path, contents, mode=None):
"""
Atomically writes contents to path using a temporary file in the same directory
diff --git a/common/kalman/SConscript b/common/kalman/SConscript
index abd7e04375..3d7011fe29 100644
--- a/common/kalman/SConscript
+++ b/common/kalman/SConscript
@@ -1,6 +1,6 @@
-Import('env')
+Import('env', 'cython_dependencies')
env.Command(['simple_kalman_impl.so'],
- ['simple_kalman_impl.pyx', 'simple_kalman_impl.pxd', 'simple_kalman_setup.py'],
- "cd common/kalman && python3 simple_kalman_setup.py build_ext --inplace")
+ cython_dependencies + ['simple_kalman_impl.pyx', 'simple_kalman_impl.pxd', 'simple_kalman_setup.py'],
+ "cd common/kalman && python3 simple_kalman_setup.py build_ext --inplace")
diff --git a/common/kalman/simple_kalman_old.py b/common/kalman/simple_kalman_old.py
index 3f7d049cc5..d11770faf6 100644
--- a/common/kalman/simple_kalman_old.py
+++ b/common/kalman/simple_kalman_old.py
@@ -8,7 +8,7 @@ class KF1D:
def __init__(self, x0, A, C, K):
self.x = x0
self.A = A
- self.C = C
+ self.C = np.atleast_2d(C)
self.K = K
self.A_K = self.A - np.dot(self.K, self.C)
diff --git a/common/kalman/tests/test_simple_kalman.py b/common/kalman/tests/test_simple_kalman.py
index c1f9f7b03c..6308759984 100644
--- a/common/kalman/tests/test_simple_kalman.py
+++ b/common/kalman/tests/test_simple_kalman.py
@@ -21,10 +21,10 @@ class TestSimpleKalman(unittest.TestCase):
K0_0 = 0.12287673
K1_0 = 0.29666309
- self.kf_old = KF1D_old(x0=np.matrix([[x0_0], [x1_0]]),
- A=np.matrix([[A0_0, A0_1], [A1_0, A1_1]]),
- C=np.matrix([C0_0, C0_1]),
- K=np.matrix([[K0_0], [K1_0]]))
+ self.kf_old = KF1D_old(x0=np.array([[x0_0], [x1_0]]),
+ A=np.array([[A0_0, A0_1], [A1_0, A1_1]]),
+ C=np.array([C0_0, C0_1]),
+ K=np.array([[K0_0], [K1_0]]))
self.kf = KF1D(x0=[[x0_0], [x1_0]],
A=[[A0_0, A0_1], [A1_0, A1_1]],
@@ -47,9 +47,8 @@ class TestSimpleKalman(unittest.TestCase):
x = self.kf.update(v_wheel)
# Compare the output x, verify that the error is less than 1e-4
- self.assertAlmostEqual(x_old[0], x[0])
- self.assertAlmostEqual(x_old[1], x[1])
-
+ np.testing.assert_almost_equal(x_old[0], x[0])
+ np.testing.assert_almost_equal(x_old[1], x[1])
def test_new_is_faster(self):
setup = """
@@ -70,10 +69,10 @@ C0_1 = 0.0
K0_0 = 0.12287673
K1_0 = 0.29666309
-kf_old = KF1D_old(x0=np.matrix([[x0_0], [x1_0]]),
- A=np.matrix([[A0_0, A0_1], [A1_0, A1_1]]),
- C=np.matrix([C0_0, C0_1]),
- K=np.matrix([[K0_0], [K1_0]]))
+kf_old = KF1D_old(x0=np.array([[x0_0], [x1_0]]),
+ A=np.array([[A0_0, A0_1], [A1_0, A1_1]]),
+ C=np.array([C0_0, C0_1]),
+ K=np.array([[K0_0], [K1_0]]))
kf = KF1D(x0=[[x0_0], [x1_0]],
A=[[A0_0, A0_1], [A1_0, A1_1]],
diff --git a/common/logging_extra.py b/common/logging_extra.py
index b5d07f2209..ce8889b410 100644
--- a/common/logging_extra.py
+++ b/common/logging_extra.py
@@ -68,8 +68,11 @@ class SwagErrorFilter(logging.Filter):
def filter(self, record):
return record.levelno < logging.ERROR
-_tmpfunc = lambda: 0
-_srcfile = os.path.normcase(_tmpfunc.__code__.co_filename)
+def _tmpfunc():
+ return 0
+
+def _srcfile():
+ return os.path.normcase(_tmpfunc.__code__.co_filename)
class SwagLogger(logging.Logger):
def __init__(self):
@@ -112,9 +115,6 @@ class SwagLogger(logging.Logger):
if args:
evt['args'] = args
evt.update(kwargs)
- ctx = self.get_ctx()
- if ctx:
- evt['ctx'] = self.get_ctx()
if 'error' in kwargs:
self.error(evt)
else:
@@ -140,7 +140,9 @@ class SwagLogger(logging.Logger):
while hasattr(f, "f_code"):
co = f.f_code
filename = os.path.normcase(co.co_filename)
- if filename == _srcfile:
+
+ # TODO: is this pylint exception correct?
+ if filename == _srcfile: # pylint: disable=comparison-with-callable
f = f.f_back
continue
sinfo = None
diff --git a/common/manager_helpers.py b/common/manager_helpers.py
deleted file mode 100644
index a8cfb3df05..0000000000
--- a/common/manager_helpers.py
+++ /dev/null
@@ -1,50 +0,0 @@
-def cputime_total(ct):
- return ct.cpuUser + ct.cpuSystem + ct.cpuChildrenUser + ct.cpuChildrenSystem
-
-
-def print_cpu_usage(first_proc, last_proc):
- r = 0
- procs = [
- ("selfdrive.controls.controlsd", 59.46),
- ("./_modeld", 48.94),
- ("./loggerd", 28.49),
- ("selfdrive.controls.plannerd", 19.77),
- ("selfdrive.controls.radard", 9.54),
- ("./_ui", 9.54),
- ("./camerad", 7.07),
- ("selfdrive.locationd.locationd", 7.13),
- ("./_sensord", 6.17),
- ("selfdrive.controls.dmonitoringd", 5.48),
- ("./boardd", 3.63),
- ("./_dmonitoringmodeld", 2.67),
- ("selfdrive.logmessaged", 2.71),
- ("selfdrive.thermald", 2.41),
- ("./paramsd", 2.18),
- ("selfdrive.locationd.calibrationd", 1.76),
- ("./proclogd", 1.54),
- ("./_gpsd", 0.09),
- ("./clocksd", 0.02),
- ("./ubloxd", 0.02),
- ("selfdrive.tombstoned", 0),
- ("./logcatd", 0),
- ("selfdrive.updated", 0),
- ]
-
- dt = (last_proc.logMonoTime - first_proc.logMonoTime) / 1e9
- print("------------------------------------------------")
- for proc_name, normal_cpu_usage in procs:
- try:
- first = [p for p in first_proc.procLog.procs if proc_name in p.cmdline][0]
- last = [p for p in last_proc.procLog.procs if proc_name in p.cmdline][0]
- cpu_time = cputime_total(last) - cputime_total(first)
- cpu_usage = cpu_time / dt * 100.
- if cpu_usage > max(normal_cpu_usage * 1.1, normal_cpu_usage + 5.0):
- print(f"Warning {proc_name} using more CPU than normal")
- r = 1
-
- print(f"{proc_name.ljust(35)} {cpu_usage:.2f}%")
- except IndexError:
- print(f"{proc_name.ljust(35)} NO METRICS FOUND")
- print("------------------------------------------------")
-
- return r
diff --git a/common/numpy_fast.py b/common/numpy_fast.py
index a5d5ad3f50..a8361214d1 100644
--- a/common/numpy_fast.py
+++ b/common/numpy_fast.py
@@ -6,6 +6,7 @@ def clip(x, lo, hi):
def interp(x, xp, fp):
N = len(xp)
+
def get_interp(xv):
hi = 0
while hi < N and xv > xp[hi]:
@@ -14,8 +15,8 @@ def interp(x, xp, fp):
return fp[-1] if hi == N and xv > xp[low] else (
fp[0] if hi == 0 else
(xv - xp[low]) * (fp[hi] - fp[low]) / (xp[hi] - xp[low]) + fp[low])
- return [get_interp(v) for v in x] if hasattr(
- x, '__iter__') else get_interp(x)
+
+ return [get_interp(v) for v in x] if hasattr(x, '__iter__') else get_interp(x)
def mean(x):
return sum(x) / len(x)
diff --git a/common/params.py b/common/params.py
index 787235bf13..d01b1b4ae9 100755
--- a/common/params.py
+++ b/common/params.py
@@ -22,10 +22,7 @@ file in place without messing with /d.
"""
import time
import os
-import string
-import binascii
import errno
-import sys
import shutil
import fcntl
import tempfile
@@ -33,6 +30,7 @@ import threading
from enum import Enum
from common.basedir import PARAMS
+
def mkdirs_exists_ok(path):
try:
os.makedirs(path)
@@ -55,6 +53,7 @@ keys = {
"AccessToken": [TxType.CLEAR_ON_MANAGER_START],
"AthenadPid": [TxType.PERSISTENT],
"CalibrationParams": [TxType.PERSISTENT],
+ "CarBatteryCapacity": [TxType.PERSISTENT],
"CarParams": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"CarParamsCache": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"CarVin": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
@@ -62,6 +61,7 @@ keys = {
"CompletedTrainingVersion": [TxType.PERSISTENT],
"ControlsParams": [TxType.PERSISTENT],
"DisablePowerDown": [TxType.PERSISTENT],
+ "DisableUpdates": [TxType.PERSISTENT],
"DoUninstall": [TxType.CLEAR_ON_MANAGER_START],
"DongleId": [TxType.PERSISTENT],
"GitBranch": [TxType.PERSISTENT],
@@ -81,6 +81,7 @@ keys = {
"IsUploadRawEnabled": [TxType.PERSISTENT],
"LastAthenaPingTime": [TxType.PERSISTENT],
"LastUpdateTime": [TxType.PERSISTENT],
+ "LastUpdateException": [TxType.PERSISTENT],
"LimitSetSpeed": [TxType.PERSISTENT],
"LimitSetSpeedNeural": [TxType.PERSISTENT],
"LiveParameters": [TxType.PERSISTENT],
@@ -108,6 +109,8 @@ keys = {
"Offroad_PandaFirmwareMismatch": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"Offroad_InvalidTime": [TxType.CLEAR_ON_MANAGER_START],
"Offroad_IsTakingSnapshot": [TxType.CLEAR_ON_MANAGER_START],
+ "Offroad_NeosUpdate": [TxType.CLEAR_ON_MANAGER_START],
+ "Offroad_UpdateFailed": [TxType.CLEAR_ON_MANAGER_START],
}
@@ -146,6 +149,10 @@ class DBAccessor():
def get(self, key):
self._check_entered()
+
+ if self._vals is None:
+ return None
+
try:
return self._vals[key]
except KeyError:
@@ -198,7 +205,8 @@ class DBReader(DBAccessor):
finally:
lock.release()
- def __exit__(self, type, value, traceback): pass
+ def __exit__(self, exc_type, exc_value, traceback):
+ pass
class DBWriter(DBAccessor):
@@ -223,14 +231,14 @@ class DBWriter(DBAccessor):
os.chmod(self._path, 0o777)
self._lock = self._get_lock(True)
self._vals = self._read_values_locked()
- except:
+ except Exception:
os.umask(self._prev_umask)
self._prev_umask = None
raise
return self
- def __exit__(self, type, value, traceback):
+ def __exit__(self, exc_type, exc_value, traceback):
self._check_entered()
try:
@@ -304,34 +312,37 @@ def read_db(params_path, key):
except IOError:
return None
+
def write_db(params_path, key, value):
if isinstance(value, str):
value = value.encode('utf8')
prev_umask = os.umask(0)
- lock = FileLock(params_path+"/.lock", True)
+ lock = FileLock(params_path + "/.lock", True)
lock.acquire()
try:
- tmp_path = tempfile.mktemp(prefix=".tmp", dir=params_path)
- with open(tmp_path, "wb") as f:
+ tmp_path = tempfile.NamedTemporaryFile(mode="wb", prefix=".tmp", dir=params_path, delete=False)
+ with tmp_path as f:
f.write(value)
f.flush()
os.fsync(f.fileno())
+ os.chmod(tmp_path.name, 0o666)
path = "%s/d/%s" % (params_path, key)
- os.rename(tmp_path, path)
+ os.rename(tmp_path.name, path)
fsync_dir(os.path.dirname(path))
finally:
os.umask(prev_umask)
lock.release()
+
class Params():
def __init__(self, db=PARAMS):
self.db = db
# create the database if it doesn't exist...
- if not os.path.exists(self.db+"/d"):
+ if not os.path.exists(self.db + "/d"):
with self.transaction(write=True):
pass
@@ -401,22 +412,3 @@ def put_nonblocking(key, val):
t = threading.Thread(target=f, args=(key, val))
t.start()
return t
-
-
-if __name__ == "__main__":
- params = Params()
- if len(sys.argv) > 2:
- params.put(sys.argv[1], sys.argv[2])
- else:
- for k in keys:
- pp = params.get(k)
- if pp is None:
- print("%s is None" % k)
- elif all(chr(c) in string.printable for c in pp):
- print("%s = %s" % (k, pp))
- else:
- print("%s = %s" % (k, binascii.hexlify(pp)))
-
- # Test multiprocess:
- # seq 0 100000 | xargs -P20 -I{} python common/params.py DongleId {} && sleep 0.05
- # while python common/params.py DongleId; do sleep 0.05; done
diff --git a/common/profiler.py b/common/profiler.py
index f8262dd83e..ac28bdac40 100644
--- a/common/profiler.py
+++ b/common/profiler.py
@@ -43,4 +43,3 @@ class Profiler():
else:
print("%30s: %9.2f percent: %3.0f" % (n, ms*1000.0, ms/self.tot*100))
print("Iter clock: %2.6f TOTAL: %2.2f" % (self.tot/self.iter, self.tot))
-
diff --git a/common/realtime.py b/common/realtime.py
index c21222e88c..e734438646 100644
--- a/common/realtime.py
+++ b/common/realtime.py
@@ -6,6 +6,7 @@ import subprocess
import multiprocessing
from cffi import FFI
+from common.android import ANDROID
from common.common_pyx import sec_since_boot # pylint: disable=no-name-in-module, import-error
@@ -20,11 +21,7 @@ ffi = FFI()
ffi.cdef("long syscall(long number, ...);")
libc = ffi.dlopen(None)
-
-def set_realtime_priority(level):
- if os.getuid() != 0:
- print("not setting priority, not root")
- return
+def _get_tid():
if platform.machine() == "x86_64":
NR_gettid = 186
elif platform.machine() == "aarch64":
@@ -32,8 +29,25 @@ def set_realtime_priority(level):
else:
raise NotImplementedError
- tid = libc.syscall(NR_gettid)
- return subprocess.call(['chrt', '-f', '-p', str(level), str(tid)])
+ return libc.syscall(NR_gettid)
+
+
+def set_realtime_priority(level):
+ if os.getuid() != 0:
+ print("not setting priority, not root")
+ return
+
+ return subprocess.call(['chrt', '-f', '-p', str(level), str(_get_tid())])
+
+def set_core_affinity(core):
+ if os.getuid() != 0:
+ print("not setting affinity, not root")
+ return
+
+ if ANDROID:
+ return subprocess.call(['taskset', '-p', str(core), str(_get_tid())])
+ else:
+ return -1
class Ratekeeper():
diff --git a/common/spinner.py b/common/spinner.py
index da8084037e..53e8ee5215 100644
--- a/common/spinner.py
+++ b/common/spinner.py
@@ -4,14 +4,17 @@ from common.basedir import BASEDIR
class Spinner():
- def __init__(self):
- try:
- self.spinner_proc = subprocess.Popen(["./spinner"],
- stdin=subprocess.PIPE,
- cwd=os.path.join(BASEDIR, "selfdrive", "ui", "spinner"),
- close_fds=True)
- except OSError:
- self.spinner_proc = None
+ def __init__(self, noop=False):
+ # spinner is currently only implemented for android
+ self.spinner_proc = None
+ if not noop:
+ try:
+ self.spinner_proc = subprocess.Popen(["./spinner"],
+ stdin=subprocess.PIPE,
+ cwd=os.path.join(BASEDIR, "selfdrive", "ui", "spinner"),
+ close_fds=True)
+ except OSError:
+ self.spinner_proc = None
def __enter__(self):
return self
@@ -36,27 +39,10 @@ class Spinner():
def __del__(self):
self.close()
- def __exit__(self, type, value, traceback):
+ def __exit__(self, exc_type, exc_value, traceback):
self.close()
-class FakeSpinner():
- def __init__(self):
- pass
-
- def __enter__(self):
- return self
-
- def update(self, _):
- pass
-
- def close(self):
- pass
-
- def __exit__(self, type, value, traceback):
- pass
-
-
if __name__ == "__main__":
import time
with Spinner() as s:
diff --git a/common/stat_live.py b/common/stat_live.py
index e528c3deac..a91c1819bb 100644
--- a/common/stat_live.py
+++ b/common/stat_live.py
@@ -32,7 +32,7 @@ class RunningStat():
self.S_last = 0.
else:
self.M = self.M_last + (new_data - self.M_last) / self.n
- self.S = self.S_last + (new_data - self.M_last) * (new_data - self.M);
+ self.S = self.S_last + (new_data - self.M_last) * (new_data - self.M)
self.M_last = self.M
self.S_last = self.S
@@ -64,7 +64,7 @@ class RunningStatFilter():
_std_last = self.raw_stat.std()
self.raw_stat.push_data(new_data)
_delta_std = self.raw_stat.std() - _std_last
- if _delta_std<=0:
+ if _delta_std <= 0:
self.filtered_stat.push_data(new_data)
else:
pass
diff --git a/common/string_helpers.py b/common/string_helpers.py
index 8a7624a277..3038605fbb 100644
--- a/common/string_helpers.py
+++ b/common/string_helpers.py
@@ -3,4 +3,4 @@ def replace_right(s, old, new, occurrence):
# replace_right('1232425', '2', ' ', 2) -> '123 4 5'
split = s.rsplit(old, occurrence)
- return new.join(split)
\ No newline at end of file
+ return new.join(split)
diff --git a/common/testing.py b/common/testing.py
deleted file mode 100644
index 7e8b16d5cf..0000000000
--- a/common/testing.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import os
-from nose.tools import nottest
-
-def phone_only(x):
- if os.path.isfile("/init.qcom.rc"):
- return x
- else:
- return nottest(x)
-
diff --git a/common/tests/test_numpy_fast.py b/common/tests/test_numpy_fast.py
index bf34de2ed7..2fb8a1cef3 100644
--- a/common/tests/test_numpy_fast.py
+++ b/common/tests/test_numpy_fast.py
@@ -1,6 +1,5 @@
import numpy as np
import unittest
-import timeit
from common.numpy_fast import interp
diff --git a/common/tests/test_params.py b/common/tests/test_params.py
index b0c7af828d..0a2ac4e12f 100644
--- a/common/tests/test_params.py
+++ b/common/tests/test_params.py
@@ -1,10 +1,12 @@
-from common.params import Params, UnknownKeyName
+import os
import threading
import time
import tempfile
import shutil
+import stat
import unittest
+from common.params import Params, UnknownKeyName
class TestParams(unittest.TestCase):
def setUp(self):
@@ -58,6 +60,12 @@ class TestParams(unittest.TestCase):
with self.assertRaises(UnknownKeyName):
self.params.get("swag")
+ def test_params_permissions(self):
+ permissions = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH
+
+ self.params.put("DongleId", "cb38263377b873ee")
+ st_mode = os.stat(f"{self.tmpdir}/d/DongleId").st_mode
+ assert (st_mode & permissions) == permissions
if __name__ == "__main__":
unittest.main()
diff --git a/common/text_window.py b/common/text_window.py
index 0d94bc7470..b815d8022a 100755
--- a/common/text_window.py
+++ b/common/text_window.py
@@ -6,20 +6,22 @@ from common.basedir import BASEDIR
class TextWindow():
- def __init__(self, s):
- try:
- self.text_proc = subprocess.Popen(["./text", s],
- stdin=subprocess.PIPE,
- cwd=os.path.join(BASEDIR, "selfdrive", "ui", "text"),
- close_fds=True)
- except OSError:
- self.text_proc = None
+ def __init__(self, s, noop=False):
+ # text window is only implemented for android currently
+ self.text_proc = None
+ if not noop:
+ try:
+ self.text_proc = subprocess.Popen(["./text", s],
+ stdin=subprocess.PIPE,
+ cwd=os.path.join(BASEDIR, "selfdrive", "ui", "text"),
+ close_fds=True)
+ except OSError:
+ self.text_proc = None
def get_status(self):
if self.text_proc is not None:
self.text_proc.poll()
return self.text_proc.returncode
-
return None
def __enter__(self):
@@ -31,38 +33,19 @@ class TextWindow():
self.text_proc = None
def wait_for_exit(self):
- while True:
- if self.get_status() == 1:
- return
- time.sleep(0.1)
+ if self.text_proc is not None:
+ while True:
+ if self.get_status() == 1:
+ return
+ time.sleep(0.1)
def __del__(self):
self.close()
- def __exit__(self, type, value, traceback):
+ def __exit__(self, exc_type, exc_value, traceback):
self.close()
-class FakeTextWindow():
- def __init__(self, s):
- pass
-
- def get_status(self):
- return 1
-
- def wait_for_exit(self):
- return
-
- def __enter__(self):
- return self
-
- def update(self, _):
- pass
-
- def __exit__(self, type, value, traceback):
- pass
-
-
if __name__ == "__main__":
text = """Traceback (most recent call last):
File "./controlsd.py", line 608, in
diff --git a/common/timeout.py b/common/timeout.py
index c2c1f69712..4d424cdc0a 100644
--- a/common/timeout.py
+++ b/common/timeout.py
@@ -25,4 +25,3 @@ class Timeout:
def __exit__(self, exc_type, exc_val, exc_tb):
signal.alarm(0)
-
diff --git a/common/transformations/.gitignore b/common/transformations/.gitignore
new file mode 100644
index 0000000000..a67290f09a
--- /dev/null
+++ b/common/transformations/.gitignore
@@ -0,0 +1,2 @@
+transformations
+transformations.cpp
diff --git a/common/transformations/README.md b/common/transformations/README.md
index 119dae630e..f10852228a 100644
--- a/common/transformations/README.md
+++ b/common/transformations/README.md
@@ -25,14 +25,14 @@ by generating a rotation matrix and multiplying.
Orientation Conventations
------
-Quaternions, rotation matrices and euler angles are three
+Quaternions, rotation matrices and euler angles are three
equivalent representations of orientation and all three are
used throughout the code base.
For euler angles the preferred convention is [roll, pitch, yaw]
which corresponds to rotations around the [x, y, z] axes. All
euler angles should always be in radians or radians/s unless
-for plotting or display purposes. For quaternions the hamilton
+for plotting or display purposes. For quaternions the hamilton
notations is preferred which is [qw, qx, qy, qz]. All quaternions
should always be normalized with a strictly positive qw. **These
quaternions are a unique representation of orientation whereas euler angles
@@ -45,11 +45,16 @@ while rotating around the rotated axes, not the original axes.
Calibration
------
-EONs are not all mounted in the exact same way. To compensate for the effects of this the vision model takes in an image that is "calibrated". This means the image is aligned so the direction of travel of the car when it is going straight and the road is flat is always in the location on the image. This calibration is defined by a pitch and yaw angle that describe the direction of travel vector in device frame.
+Device frame is aligned with the road-facing camera used by openpilot. However, when controlling the vehicle it makes more sense to think in a reference frame aligned with the vehicle. These two reference frames are not necessarily aligned. Calibration is defined as the roll, pitch and yaw angles that describe the orientation of the vehicle in device frame. The vehicle orientation is the orientation of the vehicles's body, the orientation of the vehicle can change relative to the road because of suspension movements.
+
+The roll of the vehicle is defined to be 0 when the vehicle is on a flat road and not turning. Pitch and yaw are defined as the angles that describe the direction in which the vehicle travels when it is driving on a flat road and not turning.
+
+It is important for openpilot's driving model to take in images that look as if the calibration angles were all zero. To achieve this the images input into the model are transformed with the estimated calibration angles. At the moment, roll calibration is always estimated to be zero.
+
Example
------
-To transform global Mesh3D positions and orientations (positions_ecef, quats_ecef) into the local frame described by the
+To transform global Mesh3D positions and orientations (positions_ecef, quats_ecef) into the local frame described by the
first position and orientation from Mesh3D one would do:
```
ecef_from_local = rot_from_quat(quats_ecef[0])
diff --git a/common/transformations/SConscript b/common/transformations/SConscript
new file mode 100644
index 0000000000..0f72952259
--- /dev/null
+++ b/common/transformations/SConscript
@@ -0,0 +1,8 @@
+Import('env', 'cython_dependencies')
+
+d = Dir('.')
+
+env.Command(['transformations.so'],
+ cython_dependencies + ['transformations.pxd', 'transformations.pyx',
+ 'coordinates.cc', 'orientation.cc', 'coordinates.hpp', 'orientation.hpp'],
+ 'cd ' + d.path + ' && python3 setup.py build_ext --inplace')
diff --git a/common/transformations/camera.py b/common/transformations/camera.py
index 5ca9eb57d5..b406c33fd7 100644
--- a/common/transformations/camera.py
+++ b/common/transformations/camera.py
@@ -52,6 +52,13 @@ def get_view_frame_from_road_frame(roll, pitch, yaw, height):
return np.hstack((view_from_road, [[0], [height], [0]]))
+# aka 'extrinsic_matrix'
+def get_view_frame_from_calib_frame(roll, pitch, yaw, height):
+ device_from_calib= orient.rot_from_euler([roll, pitch, yaw])
+ view_from_calib = view_frame_from_device_frame.dot(device_from_calib)
+ return np.hstack((view_from_calib, [[0], [height], [0]]))
+
+
def vp_from_ke(m):
"""
Computes the vanishing point from the product of the intrinsic and extrinsic
@@ -59,7 +66,7 @@ def vp_from_ke(m):
The vanishing point is defined as lim x->infinity C (x, 0, 0, 1).T
"""
- return (m[0, 0]/m[2,0], m[1,0]/m[2,0])
+ return (m[0, 0]/m[2, 0], m[1, 0]/m[2, 0])
def vp_from_rpy(rpy):
@@ -81,10 +88,10 @@ def normalize(img_pts, intrinsics=eon_intrinsics):
img_pts = np.array(img_pts)
input_shape = img_pts.shape
img_pts = np.atleast_2d(img_pts)
- img_pts = np.hstack((img_pts, np.ones((img_pts.shape[0],1))))
+ img_pts = np.hstack((img_pts, np.ones((img_pts.shape[0], 1))))
img_pts_normalized = img_pts.dot(intrinsics_inv.T)
img_pts_normalized[(img_pts < 0).any(axis=1)] = np.nan
- return img_pts_normalized[:,:2].reshape(input_shape)
+ return img_pts_normalized[:, :2].reshape(input_shape)
def denormalize(img_pts, intrinsics=eon_intrinsics):
@@ -93,13 +100,13 @@ def denormalize(img_pts, intrinsics=eon_intrinsics):
img_pts = np.array(img_pts)
input_shape = img_pts.shape
img_pts = np.atleast_2d(img_pts)
- img_pts = np.hstack((img_pts, np.ones((img_pts.shape[0],1))))
+ img_pts = np.hstack((img_pts, np.ones((img_pts.shape[0], 1))))
img_pts_denormalized = img_pts.dot(intrinsics.T)
- img_pts_denormalized[img_pts_denormalized[:,0] > W] = np.nan
- img_pts_denormalized[img_pts_denormalized[:,0] < 0] = np.nan
- img_pts_denormalized[img_pts_denormalized[:,1] > H] = np.nan
- img_pts_denormalized[img_pts_denormalized[:,1] < 0] = np.nan
- return img_pts_denormalized[:,:2].reshape(input_shape)
+ img_pts_denormalized[img_pts_denormalized[:, 0] > W] = np.nan
+ img_pts_denormalized[img_pts_denormalized[:, 0] < 0] = np.nan
+ img_pts_denormalized[img_pts_denormalized[:, 1] > H] = np.nan
+ img_pts_denormalized[img_pts_denormalized[:, 1] < 0] = np.nan
+ return img_pts_denormalized[:, :2].reshape(input_shape)
def device_from_ecef(pos_ecef, orientation_ecef, pt_ecef):
@@ -124,10 +131,10 @@ def img_from_device(pt_device):
pt_view = np.einsum('jk,ik->ij', view_frame_from_device_frame, pt_device)
# This function should never return negative depths
- pt_view[pt_view[:,2] < 0] = np.nan
+ pt_view[pt_view[:, 2] < 0] = np.nan
- pt_img = pt_view/pt_view[:,2:3]
- return pt_img.reshape(input_shape)[:,:2]
+ pt_img = pt_view/pt_view[:, 2:3]
+ return pt_img.reshape(input_shape)[:, :2]
def get_camera_frame_from_calib_frame(camera_frame_from_road_frame):
@@ -145,4 +152,3 @@ def pretransform_from_calib(calib):
camera_frame_from_road_frame = np.dot(eon_intrinsics, view_frame_from_road_frame)
camera_frame_from_calib_frame = get_camera_frame_from_calib_frame(camera_frame_from_road_frame)
return np.linalg.inv(camera_frame_from_calib_frame)
-
diff --git a/common/transformations/coordinates.cc b/common/transformations/coordinates.cc
new file mode 100644
index 0000000000..8a1aa0ad72
--- /dev/null
+++ b/common/transformations/coordinates.cc
@@ -0,0 +1,104 @@
+#define _USE_MATH_DEFINES
+
+#include
+#include
+#include
+
+#include "coordinates.hpp"
+
+#define DEG2RAD(x) ((x) * M_PI / 180.0)
+#define RAD2DEG(x) ((x) * 180.0 / M_PI)
+
+
+double a = 6378137; // lgtm [cpp/short-global-name]
+double b = 6356752.3142; // lgtm [cpp/short-global-name]
+double esq = 6.69437999014 * 0.001; // lgtm [cpp/short-global-name]
+double e1sq = 6.73949674228 * 0.001;
+
+
+static Geodetic to_degrees(Geodetic geodetic){
+ geodetic.lat = RAD2DEG(geodetic.lat);
+ geodetic.lon = RAD2DEG(geodetic.lon);
+ return geodetic;
+}
+
+static Geodetic to_radians(Geodetic geodetic){
+ geodetic.lat = DEG2RAD(geodetic.lat);
+ geodetic.lon = DEG2RAD(geodetic.lon);
+ return geodetic;
+}
+
+
+ECEF geodetic2ecef(Geodetic g){
+ g = to_radians(g);
+ double xi = sqrt(1.0 - esq * pow(sin(g.lat), 2));
+ double x = (a / xi + g.alt) * cos(g.lat) * cos(g.lon);
+ double y = (a / xi + g.alt) * cos(g.lat) * sin(g.lon);
+ double z = (a / xi * (1.0 - esq) + g.alt) * sin(g.lat);
+ return {x, y, z};
+}
+
+Geodetic ecef2geodetic(ECEF e){
+ // Convert from ECEF to geodetic using Ferrari's methods
+ // https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#Ferrari.27s_solution
+ double x = e.x;
+ double y = e.y;
+ double z = e.z;
+
+ double r = sqrt(x * x + y * y);
+ double Esq = a * a - b * b;
+ double F = 54 * b * b * z * z;
+ double G = r * r + (1 - esq) * z * z - esq * Esq;
+ double C = (esq * esq * F * r * r) / (pow(G, 3));
+ double S = cbrt(1 + C + sqrt(C * C + 2 * C));
+ double P = F / (3 * pow((S + 1 / S + 1), 2) * G * G);
+ double Q = sqrt(1 + 2 * esq * esq * P);
+ double r_0 = -(P * esq * r) / (1 + Q) + sqrt(0.5 * a * a*(1 + 1.0 / Q) - P * (1 - esq) * z * z / (Q * (1 + Q)) - 0.5 * P * r * r);
+ double U = sqrt(pow((r - esq * r_0), 2) + z * z);
+ double V = sqrt(pow((r - esq * r_0), 2) + (1 - esq) * z * z);
+ double Z_0 = b * b * z / (a * V);
+ double h = U * (1 - b * b / (a * V));
+
+ double lat = atan((z + e1sq * Z_0) / r);
+ double lon = atan2(y, x);
+
+ return to_degrees({lat, lon, h});
+}
+
+LocalCoord::LocalCoord(Geodetic g, ECEF e){
+ init_ecef << e.x, e.y, e.z;
+
+ g = to_radians(g);
+
+ ned2ecef_matrix <<
+ -sin(g.lat)*cos(g.lon), -sin(g.lon), -cos(g.lat)*cos(g.lon),
+ -sin(g.lat)*sin(g.lon), cos(g.lon), -cos(g.lat)*sin(g.lon),
+ cos(g.lat), 0, -sin(g.lat);
+ ecef2ned_matrix = ned2ecef_matrix.transpose();
+}
+
+NED LocalCoord::ecef2ned(ECEF e) {
+ Eigen::Vector3d ecef;
+ ecef << e.x, e.y, e.z;
+
+ Eigen::Vector3d ned = (ecef2ned_matrix * (ecef - init_ecef));
+ return {ned[0], ned[1], ned[2]};
+}
+
+ECEF LocalCoord::ned2ecef(NED n) {
+ Eigen::Vector3d ned;
+ ned << n.n, n.e, n.d;
+
+ Eigen::Vector3d ecef = (ned2ecef_matrix * ned) + init_ecef;
+ return {ecef[0], ecef[1], ecef[2]};
+}
+
+NED LocalCoord::geodetic2ned(Geodetic g) {
+ ECEF e = ::geodetic2ecef(g);
+ return ecef2ned(e);
+}
+
+Geodetic LocalCoord::ned2geodetic(NED n){
+ ECEF e = ned2ecef(n);
+ return ::ecef2geodetic(e);
+}
diff --git a/common/transformations/coordinates.hpp b/common/transformations/coordinates.hpp
new file mode 100644
index 0000000000..d8beb59ea9
--- /dev/null
+++ b/common/transformations/coordinates.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+struct ECEF {
+ double x, y, z;
+ Eigen::Vector3d to_vector(){
+ return Eigen::Vector3d(x, y, z);
+ }
+};
+
+struct NED {
+ double n, e, d;
+};
+
+struct Geodetic {
+ double lat, lon, alt;
+ bool radians=false;
+};
+
+ECEF geodetic2ecef(Geodetic g);
+Geodetic ecef2geodetic(ECEF e);
+
+class LocalCoord {
+public:
+ Eigen::Matrix3d ned2ecef_matrix;
+ Eigen::Matrix3d ecef2ned_matrix;
+ Eigen::Vector3d init_ecef;
+ LocalCoord(Geodetic g, ECEF e);
+ LocalCoord(Geodetic g) : LocalCoord(g, ::geodetic2ecef(g)) {}
+ LocalCoord(ECEF e) : LocalCoord(::ecef2geodetic(e), e) {}
+
+ NED ecef2ned(ECEF e);
+ ECEF ned2ecef(NED n);
+ NED geodetic2ned(Geodetic g);
+ Geodetic ned2geodetic(NED n);
+};
diff --git a/common/transformations/coordinates.py b/common/transformations/coordinates.py
index 864bc4d807..46cc0ded0d 100644
--- a/common/transformations/coordinates.py
+++ b/common/transformations/coordinates.py
@@ -1,108 +1,19 @@
-import numpy as np
-"""
-Coordinate transformation module. All methods accept arrays as input
-with each row as a position.
-"""
+# pylint: skip-file
+from common.transformations.orientation import numpy_wrap
+from common.transformations.transformations import (ecef2geodetic_single,
+ geodetic2ecef_single)
+from common.transformations.transformations import LocalCoord as LocalCoord_single
+class LocalCoord(LocalCoord_single):
+ ecef2ned = numpy_wrap(LocalCoord_single.ecef2ned_single, (3,), (3,))
+ ned2ecef = numpy_wrap(LocalCoord_single.ned2ecef_single, (3,), (3,))
+ geodetic2ned = numpy_wrap(LocalCoord_single.geodetic2ned_single, (3,), (3,))
+ ned2geodetic = numpy_wrap(LocalCoord_single.ned2geodetic_single, (3,), (3,))
-a = 6378137
-b = 6356752.3142
-esq = 6.69437999014 * 0.001
-e1sq = 6.73949674228 * 0.001
+geodetic2ecef = numpy_wrap(geodetic2ecef_single, (3,), (3,))
+ecef2geodetic = numpy_wrap(ecef2geodetic_single, (3,), (3,))
-def geodetic2ecef(geodetic, radians=False):
- geodetic = np.array(geodetic)
- input_shape = geodetic.shape
- geodetic = np.atleast_2d(geodetic)
-
- ratio = 1.0 if radians else (np.pi / 180.0)
- lat = ratio*geodetic[:,0]
- lon = ratio*geodetic[:,1]
- alt = geodetic[:,2]
-
- xi = np.sqrt(1 - esq * np.sin(lat)**2)
- x = (a / xi + alt) * np.cos(lat) * np.cos(lon)
- y = (a / xi + alt) * np.cos(lat) * np.sin(lon)
- z = (a / xi * (1 - esq) + alt) * np.sin(lat)
- ecef = np.array([x, y, z]).T
- return ecef.reshape(input_shape)
-
-
-def ecef2geodetic(ecef, radians=False):
- """
- Convert ECEF coordinates to geodetic using ferrari's method
- """
- # Save shape and export column
- ecef = np.atleast_1d(ecef)
- input_shape = ecef.shape
- ecef = np.atleast_2d(ecef)
- x, y, z = ecef[:, 0], ecef[:, 1], ecef[:, 2]
-
- ratio = 1.0 if radians else (180.0 / np.pi)
-
- # Conver from ECEF to geodetic using Ferrari's methods
- # https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#Ferrari.27s_solution
- r = np.sqrt(x * x + y * y)
- Esq = a * a - b * b
- F = 54 * b * b * z * z
- G = r * r + (1 - esq) * z * z - esq * Esq
- C = (esq * esq * F * r * r) / (pow(G, 3))
- S = np.cbrt(1 + C + np.sqrt(C * C + 2 * C))
- P = F / (3 * pow((S + 1 / S + 1), 2) * G * G)
- Q = np.sqrt(1 + 2 * esq * esq * P)
- r_0 = -(P * esq * r) / (1 + Q) + np.sqrt(0.5 * a * a*(1 + 1.0 / Q) - \
- P * (1 - esq) * z * z / (Q * (1 + Q)) - 0.5 * P * r * r)
- U = np.sqrt(pow((r - esq * r_0), 2) + z * z)
- V = np.sqrt(pow((r - esq * r_0), 2) + (1 - esq) * z * z)
- Z_0 = b * b * z / (a * V)
- h = U * (1 - b * b / (a * V))
- lat = ratio*np.arctan((z + e1sq * Z_0) / r)
- lon = ratio*np.arctan2(y, x)
-
- # stack the new columns and return to the original shape
- geodetic = np.column_stack((lat, lon, h))
- return geodetic.reshape(input_shape)
-
-class LocalCoord():
- """
- Allows conversions to local frames. In this case NED.
- That is: North East Down from the start position in
- meters.
- """
- def __init__(self, init_geodetic, init_ecef):
- self.init_ecef = init_ecef
- lat, lon, _ = (np.pi/180)*np.array(init_geodetic)
- self.ned2ecef_matrix = np.array([[-np.sin(lat)*np.cos(lon), -np.sin(lon), -np.cos(lat)*np.cos(lon)],
- [-np.sin(lat)*np.sin(lon), np.cos(lon), -np.cos(lat)*np.sin(lon)],
- [np.cos(lat), 0, -np.sin(lat)]])
- self.ecef2ned_matrix = self.ned2ecef_matrix.T
-
- @classmethod
- def from_geodetic(cls, init_geodetic):
- init_ecef = geodetic2ecef(init_geodetic)
- return LocalCoord(init_geodetic, init_ecef)
-
- @classmethod
- def from_ecef(cls, init_ecef):
- init_geodetic = ecef2geodetic(init_ecef)
- return LocalCoord(init_geodetic, init_ecef)
-
-
- def ecef2ned(self, ecef):
- ecef = np.array(ecef)
- return np.dot(self.ecef2ned_matrix, (ecef - self.init_ecef).T).T
-
- def ned2ecef(self, ned):
- ned = np.array(ned)
- # Transpose so that init_ecef will broadcast correctly for 1d or 2d ned.
- return (np.dot(self.ned2ecef_matrix, ned.T).T + self.init_ecef)
-
- def geodetic2ned(self, geodetic):
- ecef = geodetic2ecef(geodetic)
- return self.ecef2ned(ecef)
-
- def ned2geodetic(self, ned):
- ecef = self.ned2ecef(ned)
- return ecef2geodetic(ecef)
+geodetic_from_ecef = ecef2geodetic
+ecef_from_geodetic = geodetic2ecef
diff --git a/common/transformations/model.py b/common/transformations/model.py
index c47c9e987f..a3b46858b1 100644
--- a/common/transformations/model.py
+++ b/common/transformations/model.py
@@ -2,6 +2,7 @@ import numpy as np
from common.transformations.camera import (FULL_FRAME_SIZE, eon_focal_length,
get_view_frame_from_road_frame,
+ get_view_frame_from_calib_frame,
vp_from_ke)
# segnet
@@ -41,6 +42,17 @@ medmodel_intrinsics = np.array(
[ 0. , eon_focal_length / medmodel_zoom, MEDMODEL_CY],
[ 0. , 0. , 1.]])
+# CAL model
+CALMODEL_INPUT_SIZE = (512, 256)
+CALMODEL_YUV_SIZE = (CALMODEL_INPUT_SIZE[0], CALMODEL_INPUT_SIZE[1] * 3 // 2)
+CALMODEL_CY = 47.6
+
+calmodel_zoom = 1.5
+calmodel_intrinsics = np.array(
+ [[ eon_focal_length / calmodel_zoom, 0. , 0.5 * CALMODEL_INPUT_SIZE[0]],
+ [ 0. , eon_focal_length / calmodel_zoom, CALMODEL_CY],
+ [ 0. , 0. , 1.]])
+
# BIG model
@@ -62,6 +74,9 @@ bigmodel_frame_from_road_frame = np.dot(bigmodel_intrinsics,
medmodel_frame_from_road_frame = np.dot(medmodel_intrinsics,
get_view_frame_from_road_frame(0, 0, 0, model_height))
+medmodel_frame_from_calib_frame = np.dot(medmodel_intrinsics,
+ get_view_frame_from_calib_frame(0, 0, 0, 0))
+
model_frame_from_bigmodel_frame = np.dot(model_intrinsics, np.linalg.inv(bigmodel_intrinsics))
medmodel_frame_from_bigmodel_frame = np.dot(medmodel_intrinsics, np.linalg.inv(bigmodel_intrinsics))
@@ -100,7 +115,7 @@ def get_camera_frame_from_model_frame(camera_frame_from_road_frame, height=model
# This function is super slow, so skip it if height is very close to canonical
# TODO: speed it up!
- if abs(height - model_height) > 0.001: #
+ if abs(height - model_height) > 0.001:
camera_from_model_camera = get_model_height_transform(camera_frame_from_road_frame, height)
else:
camera_from_model_camera = np.eye(3)
@@ -130,9 +145,9 @@ def get_camera_frame_from_bigmodel_frame(camera_frame_from_road_frame):
def get_model_frame(snu_full, camera_frame_from_model_frame, size):
idxs = camera_frame_from_model_frame.dot(np.column_stack([np.tile(np.arange(size[0]), size[1]),
- np.tile(np.arange(size[1]), (size[0],1)).T.flatten(),
+ np.tile(np.arange(size[1]), (size[0], 1)).T.flatten(),
np.ones(size[0] * size[1])]).T).T.astype(int)
- calib_flat = snu_full[idxs[:,1], idxs[:,0]]
+ calib_flat = snu_full[idxs[:, 1], idxs[:, 0]]
if len(snu_full.shape) == 3:
calib = calib_flat.reshape((size[1], size[0], 3))
elif len(snu_full.shape) == 2:
diff --git a/common/transformations/orientation.cc b/common/transformations/orientation.cc
new file mode 100644
index 0000000000..086219d234
--- /dev/null
+++ b/common/transformations/orientation.cc
@@ -0,0 +1,147 @@
+#define _USE_MATH_DEFINES
+
+#include
+#include
+#include
+
+#include "orientation.hpp"
+#include "coordinates.hpp"
+
+Eigen::Quaterniond ensure_unique(Eigen::Quaterniond quat){
+ if (quat.w() > 0){
+ return quat;
+ } else {
+ return Eigen::Quaterniond(-quat.w(), -quat.x(), -quat.y(), -quat.z());
+ }
+}
+
+Eigen::Quaterniond euler2quat(Eigen::Vector3d euler){
+ Eigen::Quaterniond q;
+
+ q = Eigen::AngleAxisd(euler(2), Eigen::Vector3d::UnitZ())
+ * Eigen::AngleAxisd(euler(1), Eigen::Vector3d::UnitY())
+ * Eigen::AngleAxisd(euler(0), Eigen::Vector3d::UnitX());
+ return ensure_unique(q);
+}
+
+
+Eigen::Vector3d quat2euler(Eigen::Quaterniond quat){
+ // TODO: switch to eigen implementation if the range of the Euler angles doesn't matter anymore
+ // Eigen::Vector3d euler = quat.toRotationMatrix().eulerAngles(2, 1, 0);
+ // return {euler(2), euler(1), euler(0)};
+ double gamma = atan2(2 * (quat.w() * quat.x() + quat.y() * quat.z()), 1 - 2 * (quat.x()*quat.x() + quat.y()*quat.y()));
+ double theta = asin(2 * (quat.w() * quat.y() - quat.z() * quat.x()));
+ double psi = atan2(2 * (quat.w() * quat.z() + quat.x() * quat.y()), 1 - 2 * (quat.y()*quat.y() + quat.z()*quat.z()));
+ return {gamma, theta, psi};
+}
+
+Eigen::Matrix3d quat2rot(Eigen::Quaterniond quat){
+ return quat.toRotationMatrix();
+}
+
+Eigen::Quaterniond rot2quat(Eigen::Matrix3d rot){
+ return ensure_unique(Eigen::Quaterniond(rot));
+}
+
+Eigen::Matrix3d euler2rot(Eigen::Vector3d euler){
+ return quat2rot(euler2quat(euler));
+}
+
+Eigen::Vector3d rot2euler(Eigen::Matrix3d rot){
+ return quat2euler(rot2quat(rot));
+}
+
+Eigen::Matrix3d rot_matrix(double roll, double pitch, double yaw){
+ return euler2rot({roll, pitch, yaw});
+}
+
+Eigen::Matrix3d rot(Eigen::Vector3d axis, double angle){
+ Eigen::Quaterniond q;
+ q = Eigen::AngleAxisd(angle, axis);
+ return q.toRotationMatrix();
+}
+
+
+Eigen::Vector3d ecef_euler_from_ned(ECEF ecef_init, Eigen::Vector3d ned_pose) {
+ /*
+ Using Rotations to Build Aerospace Coordinate Systems
+ Don Koks
+ https://apps.dtic.mil/dtic/tr/fulltext/u2/a484864.pdf
+ */
+ LocalCoord converter = LocalCoord(ecef_init);
+ Eigen::Vector3d zero = ecef_init.to_vector();
+
+ Eigen::Vector3d x0 = converter.ned2ecef({1, 0, 0}).to_vector() - zero;
+ Eigen::Vector3d y0 = converter.ned2ecef({0, 1, 0}).to_vector() - zero;
+ Eigen::Vector3d z0 = converter.ned2ecef({0, 0, 1}).to_vector() - zero;
+
+ Eigen::Vector3d x1 = rot(z0, ned_pose(2)) * x0;
+ Eigen::Vector3d y1 = rot(z0, ned_pose(2)) * y0;
+ Eigen::Vector3d z1 = rot(z0, ned_pose(2)) * z0;
+
+ Eigen::Vector3d x2 = rot(y1, ned_pose(1)) * x1;
+ Eigen::Vector3d y2 = rot(y1, ned_pose(1)) * y1;
+ Eigen::Vector3d z2 = rot(y1, ned_pose(1)) * z1;
+
+ Eigen::Vector3d x3 = rot(x2, ned_pose(0)) * x2;
+ Eigen::Vector3d y3 = rot(x2, ned_pose(0)) * y2;
+
+
+ x0 = Eigen::Vector3d(1, 0, 0);
+ y0 = Eigen::Vector3d(0, 1, 0);
+ z0 = Eigen::Vector3d(0, 0, 1);
+
+ double psi = atan2(x3.dot(y0), x3.dot(x0));
+ double theta = atan2(-x3.dot(z0), sqrt(pow(x3.dot(x0), 2) + pow(x3.dot(y0), 2)));
+
+ y2 = rot(z0, psi) * y0;
+ z2 = rot(y2, theta) * z0;
+
+ double phi = atan2(y3.dot(z2), y3.dot(y2));
+
+ return {phi, theta, psi};
+}
+
+Eigen::Vector3d ned_euler_from_ecef(ECEF ecef_init, Eigen::Vector3d ecef_pose){
+ /*
+ Using Rotations to Build Aerospace Coordinate Systems
+ Don Koks
+ https://apps.dtic.mil/dtic/tr/fulltext/u2/a484864.pdf
+ */
+ LocalCoord converter = LocalCoord(ecef_init);
+
+ Eigen::Vector3d x0 = Eigen::Vector3d(1, 0, 0);
+ Eigen::Vector3d y0 = Eigen::Vector3d(0, 1, 0);
+ Eigen::Vector3d z0 = Eigen::Vector3d(0, 0, 1);
+
+ Eigen::Vector3d x1 = rot(z0, ecef_pose(2)) * x0;
+ Eigen::Vector3d y1 = rot(z0, ecef_pose(2)) * y0;
+ Eigen::Vector3d z1 = rot(z0, ecef_pose(2)) * z0;
+
+ Eigen::Vector3d x2 = rot(y1, ecef_pose(1)) * x1;
+ Eigen::Vector3d y2 = rot(y1, ecef_pose(1)) * y1;
+ Eigen::Vector3d z2 = rot(y1, ecef_pose(1)) * z1;
+
+ Eigen::Vector3d x3 = rot(x2, ecef_pose(0)) * x2;
+ Eigen::Vector3d y3 = rot(x2, ecef_pose(0)) * y2;
+
+ Eigen::Vector3d zero = ecef_init.to_vector();
+ x0 = converter.ned2ecef({1, 0, 0}).to_vector() - zero;
+ y0 = converter.ned2ecef({0, 1, 0}).to_vector() - zero;
+ z0 = converter.ned2ecef({0, 0, 1}).to_vector() - zero;
+
+ double psi = atan2(x3.dot(y0), x3.dot(x0));
+ double theta = atan2(-x3.dot(z0), sqrt(pow(x3.dot(x0), 2) + pow(x3.dot(y0), 2)));
+
+ y2 = rot(z0, psi) * y0;
+ z2 = rot(y2, theta) * z0;
+
+ double phi = atan2(y3.dot(z2), y3.dot(y2));
+
+ return {phi, theta, psi};
+}
+
+
+
+int main(void){
+}
diff --git a/common/transformations/orientation.hpp b/common/transformations/orientation.hpp
new file mode 100644
index 0000000000..da95f7099d
--- /dev/null
+++ b/common/transformations/orientation.hpp
@@ -0,0 +1,17 @@
+#pragma once
+#include
+#include "coordinates.hpp"
+
+
+Eigen::Quaterniond ensure_unique(Eigen::Quaterniond quat);
+
+Eigen::Quaterniond euler2quat(Eigen::Vector3d euler);
+Eigen::Vector3d quat2euler(Eigen::Quaterniond quat);
+Eigen::Matrix3d quat2rot(Eigen::Quaterniond quat);
+Eigen::Quaterniond rot2quat(Eigen::Matrix3d rot);
+Eigen::Matrix3d euler2rot(Eigen::Vector3d euler);
+Eigen::Vector3d rot2euler(Eigen::Matrix3d rot);
+Eigen::Matrix3d rot_matrix(double roll, double pitch, double yaw);
+Eigen::Matrix3d rot(Eigen::Vector3d axis, double angle);
+Eigen::Vector3d ecef_euler_from_ned(ECEF ecef_init, Eigen::Vector3d ned_pose);
+Eigen::Vector3d ned_euler_from_ecef(ECEF ecef_init, Eigen::Vector3d ecef_pose);
diff --git a/common/transformations/orientation.py b/common/transformations/orientation.py
index acbd4a2bf3..415e247ab2 100644
--- a/common/transformations/orientation.py
+++ b/common/transformations/orientation.py
@@ -1,295 +1,52 @@
+# pylint: skip-file
import numpy as np
-from numpy import dot, inner, array, linalg
-from common.transformations.coordinates import LocalCoord
-
-
-'''
-Vectorized functions that transform between
-rotation matrices, euler angles and quaternions.
-All support lists, array or array of arrays as inputs.
-Supports both x2y and y_from_x format (y_from_x preferred!).
-'''
-
-def euler2quat(eulers):
- eulers = array(eulers)
- if len(eulers.shape) > 1:
- output_shape = (-1,4)
- else:
- output_shape = (4,)
- eulers = np.atleast_2d(eulers)
- gamma, theta, psi = eulers[:,0], eulers[:,1], eulers[:,2]
-
- q0 = np.cos(gamma / 2) * np.cos(theta / 2) * np.cos(psi / 2) + \
- np.sin(gamma / 2) * np.sin(theta / 2) * np.sin(psi / 2)
- q1 = np.sin(gamma / 2) * np.cos(theta / 2) * np.cos(psi / 2) - \
- np.cos(gamma / 2) * np.sin(theta / 2) * np.sin(psi / 2)
- q2 = np.cos(gamma / 2) * np.sin(theta / 2) * np.cos(psi / 2) + \
- np.sin(gamma / 2) * np.cos(theta / 2) * np.sin(psi / 2)
- q3 = np.cos(gamma / 2) * np.cos(theta / 2) * np.sin(psi / 2) - \
- np.sin(gamma / 2) * np.sin(theta / 2) * np.cos(psi / 2)
-
- quats = array([q0, q1, q2, q3]).T
- for i in range(len(quats)):
- if quats[i,0] < 0:
- quats[i] = -quats[i]
- return quats.reshape(output_shape)
-
-
-def quat2euler(quats):
- quats = array(quats)
- if len(quats.shape) > 1:
- output_shape = (-1,3)
- else:
- output_shape = (3,)
- quats = np.atleast_2d(quats)
- q0, q1, q2, q3 = quats[:,0], quats[:,1], quats[:,2], quats[:,3]
-
- gamma = np.arctan2(2 * (q0 * q1 + q2 * q3), 1 - 2 * (q1**2 + q2**2))
- theta = np.arcsin(2 * (q0 * q2 - q3 * q1))
- psi = np.arctan2(2 * (q0 * q3 + q1 * q2), 1 - 2 * (q2**2 + q3**2))
-
- eulers = array([gamma, theta, psi]).T
- return eulers.reshape(output_shape)
-
-
-def quat2rot(quats):
- quats = array(quats)
- input_shape = quats.shape
- quats = np.atleast_2d(quats)
- Rs = np.zeros((quats.shape[0], 3, 3))
- q0 = quats[:, 0]
- q1 = quats[:, 1]
- q2 = quats[:, 2]
- q3 = quats[:, 3]
- Rs[:, 0, 0] = q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3
- Rs[:, 0, 1] = 2 * (q1 * q2 - q0 * q3)
- Rs[:, 0, 2] = 2 * (q0 * q2 + q1 * q3)
- Rs[:, 1, 0] = 2 * (q1 * q2 + q0 * q3)
- Rs[:, 1, 1] = q0 * q0 - q1 * q1 + q2 * q2 - q3 * q3
- Rs[:, 1, 2] = 2 * (q2 * q3 - q0 * q1)
- Rs[:, 2, 0] = 2 * (q1 * q3 - q0 * q2)
- Rs[:, 2, 1] = 2 * (q0 * q1 + q2 * q3)
- Rs[:, 2, 2] = q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3
-
- if len(input_shape) < 2:
- return Rs[0]
- else:
- return Rs
-
-
-def rot2quat(rots):
- input_shape = rots.shape
- if len(input_shape) < 3:
- rots = array([rots])
- K3 = np.empty((len(rots), 4, 4))
- K3[:, 0, 0] = (rots[:, 0, 0] - rots[:, 1, 1] - rots[:, 2, 2]) / 3.0
- K3[:, 0, 1] = (rots[:, 1, 0] + rots[:, 0, 1]) / 3.0
- K3[:, 0, 2] = (rots[:, 2, 0] + rots[:, 0, 2]) / 3.0
- K3[:, 0, 3] = (rots[:, 1, 2] - rots[:, 2, 1]) / 3.0
- K3[:, 1, 0] = K3[:, 0, 1]
- K3[:, 1, 1] = (rots[:, 1, 1] - rots[:, 0, 0] - rots[:, 2, 2]) / 3.0
- K3[:, 1, 2] = (rots[:, 2, 1] + rots[:, 1, 2]) / 3.0
- K3[:, 1, 3] = (rots[:, 2, 0] - rots[:, 0, 2]) / 3.0
- K3[:, 2, 0] = K3[:, 0, 2]
- K3[:, 2, 1] = K3[:, 1, 2]
- K3[:, 2, 2] = (rots[:, 2, 2] - rots[:, 0, 0] - rots[:, 1, 1]) / 3.0
- K3[:, 2, 3] = (rots[:, 0, 1] - rots[:, 1, 0]) / 3.0
- K3[:, 3, 0] = K3[:, 0, 3]
- K3[:, 3, 1] = K3[:, 1, 3]
- K3[:, 3, 2] = K3[:, 2, 3]
- K3[:, 3, 3] = (rots[:, 0, 0] + rots[:, 1, 1] + rots[:, 2, 2]) / 3.0
- q = np.empty((len(rots), 4))
- for i in range(len(rots)):
- _, eigvecs = linalg.eigh(K3[i].T)
- eigvecs = eigvecs[:,3:]
- q[i, 0] = eigvecs[-1]
- q[i, 1:] = -eigvecs[:-1].flatten()
- if q[i, 0] < 0:
- q[i] = -q[i]
-
- if len(input_shape) < 3:
- return q[0]
- else:
- return q
-
-
-def euler2rot(eulers):
- return rotations_from_quats(euler2quat(eulers))
-
-
-def rot2euler(rots):
- return quat2euler(quats_from_rotations(rots))
+from common.transformations.transformations import (ecef_euler_from_ned_single,
+ euler2quat_single,
+ euler2rot_single,
+ ned_euler_from_ecef_single,
+ quat2euler_single,
+ quat2rot_single,
+ rot2euler_single,
+ rot2quat_single)
+
+
+def numpy_wrap(function, input_shape, output_shape):
+ """Wrap a function to take either an input or list of inputs and return the correct shape"""
+ def f(*inps):
+ *args, inp = inps
+ inp = np.array(inp)
+ shape = inp.shape
+
+ if len(shape) == len(input_shape):
+ out_shape = output_shape
+ else:
+ out_shape = (shape[0],) + output_shape
+
+ # Add empty dimension if inputs is not a list
+ if len(shape) == len(input_shape):
+ inp.shape = (1, ) + inp.shape
+
+ result = np.asarray([function(*args, i) for i in inp])
+ result.shape = out_shape
+ return result
+ return f
+
+
+euler2quat = numpy_wrap(euler2quat_single, (3,), (4,))
+quat2euler = numpy_wrap(quat2euler_single, (4,), (3,))
+quat2rot = numpy_wrap(quat2rot_single, (4,), (3, 3))
+rot2quat = numpy_wrap(rot2quat_single, (3, 3), (4,))
+euler2rot = numpy_wrap(euler2rot_single, (3,), (3, 3))
+rot2euler = numpy_wrap(rot2euler_single, (3, 3), (3,))
+ecef_euler_from_ned = numpy_wrap(ecef_euler_from_ned_single, (3,), (3,))
+ned_euler_from_ecef = numpy_wrap(ned_euler_from_ecef_single, (3,), (3,))
quats_from_rotations = rot2quat
quat_from_rot = rot2quat
rotations_from_quats = quat2rot
-rot_from_quat= quat2rot
-rot_from_quat= quat2rot
+rot_from_quat = quat2rot
euler_from_rot = rot2euler
euler_from_quat = quat2euler
rot_from_euler = euler2rot
quat_from_euler = euler2quat
-
-
-
-
-
-
-'''
-Random helpers below
-'''
-
-
-def quat_product(q, r):
- t = np.zeros(4)
- t[0] = r[0] * q[0] - r[1] * q[1] - r[2] * q[2] - r[3] * q[3]
- t[1] = r[0] * q[1] + r[1] * q[0] - r[2] * q[3] + r[3] * q[2]
- t[2] = r[0] * q[2] + r[1] * q[3] + r[2] * q[0] - r[3] * q[1]
- t[3] = r[0] * q[3] - r[1] * q[2] + r[2] * q[1] + r[3] * q[0]
- return t
-
-
-def rot_matrix(roll, pitch, yaw):
- cr, sr = np.cos(roll), np.sin(roll)
- cp, sp = np.cos(pitch), np.sin(pitch)
- cy, sy = np.cos(yaw), np.sin(yaw)
- rr = array([[1,0,0],[0, cr,-sr],[0, sr, cr]])
- rp = array([[cp,0,sp],[0, 1,0],[-sp, 0, cp]])
- ry = array([[cy,-sy,0],[sy, cy,0],[0, 0, 1]])
- return ry.dot(rp.dot(rr))
-
-
-def rot(axis, angle):
- # Rotates around an arbitrary axis
- ret_1 = (1 - np.cos(angle)) * array([[axis[0]**2, axis[0] * axis[1], axis[0] * axis[2]], [
- axis[1] * axis[0], axis[1]**2, axis[1] * axis[2]
- ], [axis[2] * axis[0], axis[2] * axis[1], axis[2]**2]])
- ret_2 = np.cos(angle) * np.eye(3)
- ret_3 = np.sin(angle) * array([[0, -axis[2], axis[1]], [axis[2], 0, -axis[0]],
- [-axis[1], axis[0], 0]])
- return ret_1 + ret_2 + ret_3
-
-
-def ecef_euler_from_ned(ned_ecef_init, ned_pose):
- '''
- Got it from here:
- Using Rotations to Build Aerospace Coordinate Systems
- -Don Koks
- '''
- converter = LocalCoord.from_ecef(ned_ecef_init)
- x0 = converter.ned2ecef([1, 0, 0]) - converter.ned2ecef([0, 0, 0])
- y0 = converter.ned2ecef([0, 1, 0]) - converter.ned2ecef([0, 0, 0])
- z0 = converter.ned2ecef([0, 0, 1]) - converter.ned2ecef([0, 0, 0])
-
- x1 = rot(z0, ned_pose[2]).dot(x0)
- y1 = rot(z0, ned_pose[2]).dot(y0)
- z1 = rot(z0, ned_pose[2]).dot(z0)
-
- x2 = rot(y1, ned_pose[1]).dot(x1)
- y2 = rot(y1, ned_pose[1]).dot(y1)
- z2 = rot(y1, ned_pose[1]).dot(z1)
-
- x3 = rot(x2, ned_pose[0]).dot(x2)
- y3 = rot(x2, ned_pose[0]).dot(y2)
- #z3 = rot(x2, ned_pose[0]).dot(z2)
-
- x0 = array([1, 0, 0])
- y0 = array([0, 1, 0])
- z0 = array([0, 0, 1])
-
- psi = np.arctan2(inner(x3, y0), inner(x3, x0))
- theta = np.arctan2(-inner(x3, z0), np.sqrt(inner(x3, x0)**2 + inner(x3, y0)**2))
- y2 = rot(z0, psi).dot(y0)
- z2 = rot(y2, theta).dot(z0)
- phi = np.arctan2(inner(y3, z2), inner(y3, y2))
-
- ret = array([phi, theta, psi])
- return ret
-
-
-def ned_euler_from_ecef(ned_ecef_init, ecef_poses):
- '''
- Got the math from here:
- Using Rotations to Build Aerospace Coordinate Systems
- -Don Koks
-
- Also accepts array of ecef_poses and array of ned_ecef_inits.
- Where each row is a pose and an ecef_init.
- '''
- ned_ecef_init = array(ned_ecef_init)
- ecef_poses = array(ecef_poses)
- output_shape = ecef_poses.shape
- ned_ecef_init = np.atleast_2d(ned_ecef_init)
- if ned_ecef_init.shape[0] == 1:
- ned_ecef_init = np.tile(ned_ecef_init[0], (output_shape[0], 1))
- ecef_poses = np.atleast_2d(ecef_poses)
-
- ned_poses = np.zeros(ecef_poses.shape)
- for i, ecef_pose in enumerate(ecef_poses):
- converter = LocalCoord.from_ecef(ned_ecef_init[i])
- x0 = array([1, 0, 0])
- y0 = array([0, 1, 0])
- z0 = array([0, 0, 1])
-
- x1 = rot(z0, ecef_pose[2]).dot(x0)
- y1 = rot(z0, ecef_pose[2]).dot(y0)
- z1 = rot(z0, ecef_pose[2]).dot(z0)
-
- x2 = rot(y1, ecef_pose[1]).dot(x1)
- y2 = rot(y1, ecef_pose[1]).dot(y1)
- z2 = rot(y1, ecef_pose[1]).dot(z1)
-
- x3 = rot(x2, ecef_pose[0]).dot(x2)
- y3 = rot(x2, ecef_pose[0]).dot(y2)
- #z3 = rot(x2, ecef_pose[0]).dot(z2)
-
- x0 = converter.ned2ecef([1, 0, 0]) - converter.ned2ecef([0, 0, 0])
- y0 = converter.ned2ecef([0, 1, 0]) - converter.ned2ecef([0, 0, 0])
- z0 = converter.ned2ecef([0, 0, 1]) - converter.ned2ecef([0, 0, 0])
-
- psi = np.arctan2(inner(x3, y0), inner(x3, x0))
- theta = np.arctan2(-inner(x3, z0), np.sqrt(inner(x3, x0)**2 + inner(x3, y0)**2))
- y2 = rot(z0, psi).dot(y0)
- z2 = rot(y2, theta).dot(z0)
- phi = np.arctan2(inner(y3, z2), inner(y3, y2))
- ned_poses[i] = array([phi, theta, psi])
-
- return ned_poses.reshape(output_shape)
-
-
-def ecef2car(car_ecef, psi, theta, points_ecef, ned_converter):
- """
- TODO: add roll rotation
- Converts an array of points in ecef coordinates into
- x-forward, y-left, z-up coordinates
- Parameters
- ----------
- psi: yaw, radian
- theta: pitch, radian
- Returns
- -------
- [x, y, z] coordinates in car frame
- """
-
- # input is an array of points in ecef cocrdinates
- # output is an array of points in car's coordinate (x-front, y-left, z-up)
-
- # convert points to NED
- points_ned = []
- for p in points_ecef:
- points_ned.append(ned_converter.ecef2ned_matrix.dot(array(p) - car_ecef))
-
- points_ned = np.vstack(points_ned).T
-
- # n, e, d -> x, y, z
- # Calculate relative postions and rotate wrt to heading and pitch of car
- invert_R = array([[1., 0., 0.], [0., -1., 0.], [0., 0., -1.]])
-
- c, s = np.cos(psi), np.sin(psi)
- yaw_R = array([[c, s, 0.], [-s, c, 0.], [0., 0., 1.]])
-
- c, s = np.cos(theta), np.sin(theta)
- pitch_R = array([[c, 0., -s], [0., 1., 0.], [s, 0., c]])
-
- return dot(pitch_R, dot(yaw_R, dot(invert_R, points_ned)))
diff --git a/common/transformations/setup.py b/common/transformations/setup.py
new file mode 100644
index 0000000000..c239a97450
--- /dev/null
+++ b/common/transformations/setup.py
@@ -0,0 +1,42 @@
+import os
+import numpy
+import sysconfig
+
+from Cython.Build import cythonize
+from Cython.Distutils import build_ext
+from distutils.core import Extension, setup # pylint: disable=import-error,no-name-in-module
+
+def get_ext_filename_without_platform_suffix(filename):
+ name, ext = os.path.splitext(filename)
+ ext_suffix = sysconfig.get_config_var('EXT_SUFFIX')
+
+ if ext_suffix == ext:
+ return filename
+
+ ext_suffix = ext_suffix.replace(ext, '')
+ idx = name.find(ext_suffix)
+
+ if idx == -1:
+ return filename
+ else:
+ return name[:idx] + ext
+
+
+class BuildExtWithoutPlatformSuffix(build_ext):
+ def get_ext_filename(self, ext_name):
+ filename = super().get_ext_filename(ext_name)
+ return get_ext_filename_without_platform_suffix(filename)
+
+
+setup(
+ name='Cython transformations wrapper',
+ cmdclass={'build_ext': BuildExtWithoutPlatformSuffix},
+ ext_modules=cythonize(
+ Extension(
+ "transformations",
+ sources=["transformations.pyx"],
+ language="c++",
+ extra_compile_args=["-std=c++14"],
+ include_dirs=[numpy.get_include()],
+ )
+))
diff --git a/common/transformations/tests/test_coordinates.py b/common/transformations/tests/test_coordinates.py
index 82fdc35fbe..dc70faed0b 100755
--- a/common/transformations/tests/test_coordinates.py
+++ b/common/transformations/tests/test_coordinates.py
@@ -11,12 +11,6 @@ geodetic_positions = np.array([[37.7610403, -122.4778699, 115],
[15.1392514, 103.6976037, 24],
[24.2302229, 44.2835412, 1650]])
-geodetic_positions_radians = np.array([[0.65905448, -2.13764209, 115],
- [0.47968789, -1.19706477, 2380],
- [0.5670869, -1.98361593, -6],
- [0.26422978, 1.80986461, 24],
- [0.42289717, 0.7728936, 1650]])
-
ecef_positions = np.array([[-2711076.55270557, -4259167.14692758, 3884579.87669935],
[ 2068042.69652729, -5273435.40316622, 2927004.89190746],
[-2160412.60461669, -4932588.89873832, 3406542.29652851],
@@ -50,7 +44,6 @@ ned_offsets_batch = np.array([[ 53.88103168, 43.83445935, -46.27488057],
[ 78.56272609, 18.53100158, -43.25290759]])
-
class TestNED(unittest.TestCase):
def test_small_distances(self):
start_geodetic = np.array([33.8042184, -117.888593, 0.0])
@@ -72,18 +65,13 @@ class TestNED(unittest.TestCase):
def test_ecef_geodetic(self):
# testing single
np.testing.assert_allclose(ecef_positions[0], coord.geodetic2ecef(geodetic_positions[0]), rtol=1e-9)
- np.testing.assert_allclose(geodetic_positions[0,:2], coord.ecef2geodetic(ecef_positions[0])[:2], rtol=1e-9)
- np.testing.assert_allclose(geodetic_positions[0,2], coord.ecef2geodetic(ecef_positions[0])[2], rtol=1e-9, atol=1e-4)
+ np.testing.assert_allclose(geodetic_positions[0, :2], coord.ecef2geodetic(ecef_positions[0])[:2], rtol=1e-9)
+ np.testing.assert_allclose(geodetic_positions[0, 2], coord.ecef2geodetic(ecef_positions[0])[2], rtol=1e-9, atol=1e-4)
- np.testing.assert_allclose(geodetic_positions[:,:2], coord.ecef2geodetic(ecef_positions)[:,:2], rtol=1e-9)
- np.testing.assert_allclose(geodetic_positions[:,2], coord.ecef2geodetic(ecef_positions)[:,2], rtol=1e-9, atol=1e-4)
+ np.testing.assert_allclose(geodetic_positions[:, :2], coord.ecef2geodetic(ecef_positions)[:, :2], rtol=1e-9)
+ np.testing.assert_allclose(geodetic_positions[:, 2], coord.ecef2geodetic(ecef_positions)[:, 2], rtol=1e-9, atol=1e-4)
np.testing.assert_allclose(ecef_positions, coord.geodetic2ecef(geodetic_positions), rtol=1e-9)
- np.testing.assert_allclose(geodetic_positions_radians[0], coord.ecef2geodetic(ecef_positions[0], radians=True), rtol=1e-5)
- np.testing.assert_allclose(geodetic_positions_radians[:,:2], coord.ecef2geodetic(ecef_positions, radians=True)[:,:2], rtol=1e-7)
- np.testing.assert_allclose(geodetic_positions_radians[:,2], coord.ecef2geodetic(ecef_positions, radians=True)[:,2], rtol=1e-7, atol=1e-4)
-
-
def test_ned(self):
for ecef_pos in ecef_positions:
@@ -95,11 +83,10 @@ class TestNED(unittest.TestCase):
for geo_pos in geodetic_positions:
converter = coord.LocalCoord.from_geodetic(geo_pos)
geo_pos_moved = geo_pos + np.array([0, 0, 10])
- geo_pos_double_converted_moved = converter.ned2geodetic(converter.geodetic2ned(geo_pos) + np.array([0,0,-10]))
+ geo_pos_double_converted_moved = converter.ned2geodetic(converter.geodetic2ned(geo_pos) + np.array([0, 0, -10]))
np.testing.assert_allclose(geo_pos_moved[:2], geo_pos_double_converted_moved[:2], rtol=1e-9, atol=1e-6)
np.testing.assert_allclose(geo_pos_moved[2], geo_pos_double_converted_moved[2], rtol=1e-9, atol=1e-4)
-
def test_ned_saved_results(self):
for i, ecef_pos in enumerate(ecef_positions):
converter = coord.LocalCoord.from_ecef(ecef_pos)
diff --git a/common/transformations/tests/test_orientation.py b/common/transformations/tests/test_orientation.py
index 1e85c81a0a..50978e1a63 100755
--- a/common/transformations/tests/test_orientation.py
+++ b/common/transformations/tests/test_orientation.py
@@ -61,8 +61,7 @@ class TestOrientation(unittest.TestCase):
for i in range(len(eulers)):
np.testing.assert_allclose(ned_eulers[i], ned_euler_from_ecef(ecef_positions[i], eulers[i]), rtol=1e-7)
#np.testing.assert_allclose(eulers[i], ecef_euler_from_ned(ecef_positions[i], ned_eulers[i]), rtol=1e-7)
- np.testing.assert_allclose(ned_eulers, ned_euler_from_ecef(ecef_positions, eulers), rtol=1e-7)
-
+ # np.testing.assert_allclose(ned_eulers, ned_euler_from_ecef(ecef_positions, eulers), rtol=1e-7)
if __name__ == "__main__":
diff --git a/common/transformations/transformations.pxd b/common/transformations/transformations.pxd
new file mode 100644
index 0000000000..cb3ee53b19
--- /dev/null
+++ b/common/transformations/transformations.pxd
@@ -0,0 +1,71 @@
+from libcpp cimport bool
+
+cdef extern from "orientation.cc":
+ pass
+
+cdef extern from "orientation.hpp":
+ cdef cppclass Quaternion "Eigen::Quaterniond":
+ Quaternion()
+ Quaternion(double, double, double, double)
+ double w()
+ double x()
+ double y()
+ double z()
+
+ cdef cppclass Vector3 "Eigen::Vector3d":
+ Vector3()
+ Vector3(double, double, double)
+ double operator()(int)
+
+ cdef cppclass Matrix3 "Eigen::Matrix3d":
+ Matrix3()
+ Matrix3(double*)
+
+ double operator()(int, int)
+
+ Quaternion euler2quat(Vector3)
+ Vector3 quat2euler(Quaternion)
+ Matrix3 quat2rot(Quaternion)
+ Quaternion rot2quat(Matrix3)
+ Vector3 rot2euler(Matrix3)
+ Matrix3 euler2rot(Vector3)
+ Matrix3 rot_matrix(double, double, double)
+ Vector3 ecef_euler_from_ned(ECEF, Vector3)
+ Vector3 ned_euler_from_ecef(ECEF, Vector3)
+
+
+cdef extern from "coordinates.cc":
+ cdef struct ECEF:
+ double x
+ double y
+ double z
+
+ cdef struct NED:
+ double n
+ double e
+ double d
+
+ cdef struct Geodetic:
+ double lat
+ double lon
+ double alt
+ bool radians
+
+ ECEF geodetic2ecef(Geodetic)
+ Geodetic ecef2geodetic(ECEF)
+
+ cdef cppclass LocalCoord_c "LocalCoord":
+ Matrix3 ned2ecef_matrix
+ Matrix3 ecef2ned_matrix
+
+ LocalCoord_c(Geodetic, ECEF)
+ LocalCoord_c(Geodetic)
+ LocalCoord_c(ECEF)
+
+ NED ecef2ned(ECEF)
+ ECEF ned2ecef(NED)
+ NED geodetic2ned(Geodetic)
+ Geodetic ned2geodetic(NED)
+
+cdef extern from "coordinates.hpp":
+ pass
diff --git a/common/transformations/transformations.pyx b/common/transformations/transformations.pyx
new file mode 100644
index 0000000000..194257e037
--- /dev/null
+++ b/common/transformations/transformations.pyx
@@ -0,0 +1,172 @@
+from transformations cimport Matrix3, Vector3, Quaternion
+from transformations cimport ECEF, NED, Geodetic
+
+from transformations cimport euler2quat as euler2quat_c
+from transformations cimport quat2euler as quat2euler_c
+from transformations cimport quat2rot as quat2rot_c
+from transformations cimport rot2quat as rot2quat_c
+from transformations cimport euler2rot as euler2rot_c
+from transformations cimport rot2euler as rot2euler_c
+from transformations cimport rot_matrix as rot_matrix_c
+from transformations cimport ecef_euler_from_ned as ecef_euler_from_ned_c
+from transformations cimport ned_euler_from_ecef as ned_euler_from_ecef_c
+from transformations cimport geodetic2ecef as geodetic2ecef_c
+from transformations cimport ecef2geodetic as ecef2geodetic_c
+from transformations cimport LocalCoord_c
+
+
+import cython
+import numpy as np
+cimport numpy as np
+
+cdef np.ndarray[double, ndim=2] matrix2numpy(Matrix3 m):
+ return np.array([
+ [m(0, 0), m(0, 1), m(0, 2)],
+ [m(1, 0), m(1, 1), m(1, 2)],
+ [m(2, 0), m(2, 1), m(2, 2)],
+ ])
+
+cdef Matrix3 numpy2matrix (np.ndarray[double, ndim=2, mode="fortran"] m):
+ assert m.shape[0] == 3
+ assert m.shape[1] == 3
+ return Matrix3(m.data)
+
+cdef ECEF list2ecef(ecef):
+ cdef ECEF e;
+ e.x = ecef[0]
+ e.y = ecef[1]
+ e.z = ecef[2]
+ return e
+
+cdef NED list2ned(ned):
+ cdef NED n;
+ n.n = ned[0]
+ n.e = ned[1]
+ n.d = ned[2]
+ return n
+
+cdef Geodetic list2geodetic(geodetic):
+ cdef Geodetic g
+ g.lat = geodetic[0]
+ g.lon = geodetic[1]
+ g.alt = geodetic[2]
+ return g
+
+def euler2quat_single(euler):
+ cdef Vector3 e = Vector3(euler[0], euler[1], euler[2])
+ cdef Quaternion q = euler2quat_c(e)
+ return [q.w(), q.x(), q.y(), q.z()]
+
+def quat2euler_single(quat):
+ cdef Quaternion q = Quaternion(quat[0], quat[1], quat[2], quat[3])
+ cdef Vector3 e = quat2euler_c(q);
+ return [e(0), e(1), e(2)]
+
+def quat2rot_single(quat):
+ cdef Quaternion q = Quaternion(quat[0], quat[1], quat[2], quat[3])
+ cdef Matrix3 r = quat2rot_c(q)
+ return matrix2numpy(r)
+
+def rot2quat_single(rot):
+ cdef Matrix3 r = numpy2matrix(np.asfortranarray(rot, dtype=np.double))
+ cdef Quaternion q = rot2quat_c(r)
+ return [q.w(), q.x(), q.y(), q.z()]
+
+def euler2rot_single(euler):
+ cdef Vector3 e = Vector3(euler[0], euler[1], euler[2])
+ cdef Matrix3 r = euler2rot_c(e)
+ return matrix2numpy(r)
+
+def rot2euler_single(rot):
+ cdef Matrix3 r = numpy2matrix(np.asfortranarray(rot, dtype=np.double))
+ cdef Vector3 e = rot2euler_c(r)
+ return [e(0), e(1), e(2)]
+
+def rot_matrix(roll, pitch, yaw):
+ return matrix2numpy(rot_matrix_c(roll, pitch, yaw))
+
+def ecef_euler_from_ned_single(ecef_init, ned_pose):
+ cdef ECEF init = list2ecef(ecef_init)
+ cdef Vector3 pose = Vector3(ned_pose[0], ned_pose[1], ned_pose[2])
+
+ cdef Vector3 e = ecef_euler_from_ned_c(init, pose)
+ return [e(0), e(1), e(2)]
+
+def ned_euler_from_ecef_single(ecef_init, ecef_pose):
+ cdef ECEF init = list2ecef(ecef_init)
+ cdef Vector3 pose = Vector3(ecef_pose[0], ecef_pose[1], ecef_pose[2])
+
+ cdef Vector3 e = ned_euler_from_ecef_c(init, pose)
+ return [e(0), e(1), e(2)]
+
+def geodetic2ecef_single(geodetic):
+ cdef Geodetic g = list2geodetic(geodetic)
+ cdef ECEF e = geodetic2ecef_c(g)
+ return [e.x, e.y, e.z]
+
+def ecef2geodetic_single(ecef):
+ cdef ECEF e = list2ecef(ecef)
+ cdef Geodetic g = ecef2geodetic_c(e)
+ return [g.lat, g.lon, g.alt]
+
+
+cdef class LocalCoord:
+ cdef LocalCoord_c * lc
+
+ def __init__(self, geodetic=None, ecef=None):
+ assert (geodetic is not None) or (ecef is not None)
+ if geodetic is not None:
+ self.lc = new LocalCoord_c(list2geodetic(geodetic))
+ elif ecef is not None:
+ self.lc = new LocalCoord_c(list2ecef(ecef))
+
+ @property
+ def ned2ecef_matrix(self):
+ return matrix2numpy(self.lc.ned2ecef_matrix)
+
+ @property
+ def ecef2ned_matrix(self):
+ return matrix2numpy(self.lc.ecef2ned_matrix)
+
+ @property
+ def ned_from_ecef_matrix(self):
+ return self.ecef2ned_matrix
+
+ @property
+ def ecef_from_ned_matrix(self):
+ return self.ned2ecef_matrix
+
+ @classmethod
+ def from_geodetic(cls, geodetic):
+ return cls(geodetic=geodetic)
+
+ @classmethod
+ def from_ecef(cls, ecef):
+ return cls(ecef=ecef)
+
+ def ecef2ned_single(self, ecef):
+ assert self.lc
+ cdef ECEF e = list2ecef(ecef)
+ cdef NED n = self.lc.ecef2ned(e)
+ return [n.n, n.e, n.d]
+
+ def ned2ecef_single(self, ned):
+ assert self.lc
+ cdef NED n = list2ned(ned)
+ cdef ECEF e = self.lc.ned2ecef(n)
+ return [e.x, e.y, e.z]
+
+ def geodetic2ned_single(self, geodetic):
+ assert self.lc
+ cdef Geodetic g = list2geodetic(geodetic)
+ cdef NED n = self.lc.geodetic2ned(g)
+ return [n.n, n.e, n.d]
+
+ def ned2geodetic_single(self, ned):
+ assert self.lc
+ cdef NED n = list2ned(ned)
+ cdef Geodetic g = self.lc.ned2geodetic(n)
+ return [g.lat, g.lon, g.alt]
+
+ def __dealloc__(self):
+ del self.lc
diff --git a/common/window.py b/common/window.py
index f93f532cb4..62f8cb9e0b 100644
--- a/common/window.py
+++ b/common/window.py
@@ -1,35 +1,35 @@
import sys
-import pygame
+import pygame # pylint: disable=import-error
+import cv2 # pylint: disable=import-error
class Window():
def __init__(self, w, h, caption="window", double=False):
self.w = w
self.h = h
- pygame.init()
+ pygame.display.init()
pygame.display.set_caption(caption)
self.double = double
if self.double:
- self.screen = pygame.display.set_mode((w*2,h*2), pygame.DOUBLEBUF)
+ self.screen = pygame.display.set_mode((w*2, h*2))
else:
- self.screen = pygame.display.set_mode((w,h), pygame.DOUBLEBUF)
- self.camera_surface = pygame.surface.Surface((w,h), 0, 24).convert()
+ self.screen = pygame.display.set_mode((w, h))
def draw(self, out):
- pygame.surfarray.blit_array(self.camera_surface, out.swapaxes(0,1))
+ pygame.event.pump()
if self.double:
- camera_surface_2x = pygame.transform.scale2x(self.camera_surface)
- self.screen.blit(camera_surface_2x, (0, 0))
+ out2 = cv2.resize(out, (self.w*2, self.h*2))
+ pygame.surfarray.blit_array(self.screen, out2.swapaxes(0, 1))
else:
- self.screen.blit(self.camera_surface, (0, 0))
+ pygame.surfarray.blit_array(self.screen, out.swapaxes(0, 1))
pygame.display.flip()
-
+
def getkey(self):
while 1:
event = pygame.event.wait()
- if event.type == QUIT:
+ if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
- if event.type == KEYDOWN:
+ if event.type == pygame.KEYDOWN:
return event.key
def getclick(self):
@@ -40,10 +40,9 @@ class Window():
if __name__ == "__main__":
import numpy as np
- win = Window(200, 200)
- img = np.zeros((200,200,3), np.uint8)
+ win = Window(200, 200, double=True)
+ img = np.zeros((200, 200, 3), np.uint8)
while 1:
print("draw")
img += 1
win.draw(img)
-
diff --git a/external/bin/capnpc-java b/external/bin/capnpc-java
new file mode 100755
index 0000000000..55af5b5763
Binary files /dev/null and b/external/bin/capnpc-java differ
diff --git a/external/opencl/intel-opencl-devel_0r3.1-58621_amd64.deb b/external/opencl/intel-opencl-devel_0r3.1-58621_amd64.deb
deleted file mode 100644
index 52cd5b3a72..0000000000
--- a/external/opencl/intel-opencl-devel_0r3.1-58621_amd64.deb
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:e3c75edadf2e267be8a18870cafc911ea23d3b52dcff07fbe025edf815c06f5d
-size 68732
diff --git a/external/opencl/intel.icd b/external/opencl/intel.icd
deleted file mode 100644
index b31f24d7bc..0000000000
--- a/external/opencl/intel.icd
+++ /dev/null
@@ -1 +0,0 @@
-/opt/intel/opencl-1.2-6.4.0.37/lib64/libintelocl.so
diff --git a/external/opencl/opencl-1.2-base-pset_6.4.0.37-2_all.deb b/external/opencl/opencl-1.2-base-pset_6.4.0.37-2_all.deb
deleted file mode 100644
index a3c7fba5f4..0000000000
--- a/external/opencl/opencl-1.2-base-pset_6.4.0.37-2_all.deb
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:381814ea42344b895624597bf31c24ebc13f3449aaaaf65245f4a041d953b4c6
-size 17276236
diff --git a/external/opencl/opencl-1.2-base_6.4.0.37-2_amd64.deb b/external/opencl/opencl-1.2-base_6.4.0.37-2_amd64.deb
deleted file mode 100644
index feff0b9705..0000000000
--- a/external/opencl/opencl-1.2-base_6.4.0.37-2_amd64.deb
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:25aaa33f5c338b6dcc33436fdebb5e6ad727cf85a9fae921be8d3b834166ab01
-size 11432
diff --git a/external/opencl/opencl-1.2-intel-cpu_6.4.0.37-2_amd64.deb b/external/opencl/opencl-1.2-intel-cpu_6.4.0.37-2_amd64.deb
deleted file mode 100644
index dd17f9b0b6..0000000000
--- a/external/opencl/opencl-1.2-intel-cpu_6.4.0.37-2_amd64.deb
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:f7300ebee63820b519c54a50c93847516dcaf37765a698826fde666990747459
-size 20290860
diff --git a/external/simpleperf/utils.py b/external/simpleperf/utils.py
index 843e61212d..4077039846 100644
--- a/external/simpleperf/utils.py
+++ b/external/simpleperf/utils.py
@@ -101,7 +101,7 @@ def get_host_binary_path(binary_name):
elif '.' not in binary_name:
binary_name += '.exe'
dir = os.path.join(dir, 'windows')
- elif sys.platform == 'darwin': # OSX
+ elif sys.platform == 'darwin': # OSX
if binary_name.endswith('.so'):
binary_name = binary_name[0:-3] + '.dylib'
dir = os.path.join(dir, 'darwin')
@@ -220,11 +220,9 @@ class AdbHelper(object):
self.adb_path = adb_path
self.enable_switch_to_root = enable_switch_to_root
-
def run(self, adb_args):
return self.run_and_return_output(adb_args)[0]
-
def run_and_return_output(self, adb_args, stdout_file=None, log_output=True):
adb_args = [self.adb_path] + adb_args
log_debug('run adb cmd: %s' % adb_args)
@@ -247,14 +245,12 @@ class AdbHelper(object):
def check_run(self, adb_args):
self.check_run_and_return_output(adb_args)
-
def check_run_and_return_output(self, adb_args, stdout_file=None, log_output=True):
result, stdoutdata = self.run_and_return_output(adb_args, stdout_file, log_output)
if not result:
log_exit('run "adb %s" failed' % adb_args)
return stdoutdata
-
def _unroot(self):
result, stdoutdata = self.run_and_return_output(['shell', 'whoami'])
if not result:
@@ -266,7 +262,6 @@ class AdbHelper(object):
self.run(['wait-for-device'])
time.sleep(1)
-
def switch_to_root(self):
if not self.enable_switch_to_root:
self._unroot()
@@ -292,7 +287,6 @@ class AdbHelper(object):
def set_property(self, name, value):
return self.run(['shell', 'setprop', name, value])
-
def get_device_arch(self):
output = self.check_run_and_return_output(['shell', 'uname', '-m'])
if 'aarch64' in output:
@@ -305,7 +299,6 @@ class AdbHelper(object):
return 'x86'
log_fatal('unsupported architecture: %s' % output.strip())
-
def get_android_version(self):
build_version = self.get_property('ro.build.version.release')
android_version = 0
diff --git a/flake8_openpilot.sh b/flake8_openpilot.sh
deleted file mode 100755
index a2d99655cf..0000000000
--- a/flake8_openpilot.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env bash
-
-# only pyflakes check (--select=F)
-RESULT=$(python3 -m flake8 --select=F $(eval echo $(cat <(find cereal) <(find opendbc) release/files_common release/files_common | tr '\n' ' ') | tr ' ' '\n' | grep "\.py$"))
-if [[ $RESULT ]]; then
- echo "Pyflakes found errors in the code. Please fix and try again"
- echo "$RESULT"
- exit 1
-fi
diff --git a/installer/updater/test_updater.py b/installer/updater/test_updater.py
new file mode 100755
index 0000000000..6e811921de
--- /dev/null
+++ b/installer/updater/test_updater.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+import os
+import shutil
+import subprocess
+import tempfile
+import time
+import unittest
+
+from common.basedir import BASEDIR
+
+UPDATER_PATH = os.path.join(BASEDIR, "installer/updater")
+UPDATER = os.path.join(UPDATER_PATH, "updater")
+UPDATE_MANIFEST = os.path.join(UPDATER_PATH, "update.json")
+
+
+class TestUpdater(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ # test that the updater builds
+ cls.assertTrue(f"cd {UPDATER_PATH} && make clean && make", "updater failed to build")
+
+ # restore the checked-in version, since that's what actually runs on devices
+ os.system(f"git reset --hard {UPDATER_PATH}")
+
+ def setUp(self):
+ self._clear_dir()
+
+ def tearDown(self):
+ self._clear_dir()
+
+ def _clear_dir(self):
+ if os.path.isdir("/data/neoupdate"):
+ shutil.rmtree("/data/neoupdate")
+
+ def _assert_ok(self, cmd, msg=None):
+ self.assertTrue(os.system(cmd) == 0, msg)
+
+ def _assert_fails(self, cmd):
+ self.assertFalse(os.system(cmd) == 0)
+
+ def test_background_download(self):
+ self._assert_ok(f"{UPDATER} bgcache 'file://{UPDATE_MANIFEST}'")
+
+ def test_background_download_bad_manifest(self):
+ # update with bad manifest should fail
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".json") as f:
+ f.write("{}")
+ self._assert_fails(f"{UPDATER} bgcache 'file://{f.name}'")
+
+ def test_cache_resume(self):
+ self._assert_ok(f"{UPDATER} bgcache 'file://{UPDATE_MANIFEST}'")
+ # a full download takes >1m, but resuming from fully cached should only be a few seconds
+ start_time = time.monotonic()
+ self._assert_ok(f"{UPDATER} bgcache 'file://{UPDATE_MANIFEST}'")
+ self.assertLess(time.monotonic() - start_time, 10)
+
+ # make sure we can recover from corrupt downloads
+ def test_recover_from_corrupt(self):
+ # download the whole update
+ self._assert_ok(f"{UPDATER} bgcache 'file://{UPDATE_MANIFEST}'")
+
+ # write some random bytes
+ for f in os.listdir("/data/neoupdate"):
+ with open(os.path.join("/data/neoupdate", f), "ab") as f:
+ f.write(b"\xab"*20)
+
+ # this attempt should fail, then it unlinks
+ self._assert_fails(f"{UPDATER} bgcache 'file://{UPDATE_MANIFEST}'")
+
+ # now it should pass
+ self._assert_ok(f"{UPDATER} bgcache 'file://{UPDATE_MANIFEST}'")
+
+ # simple test that the updater doesn't crash in UI mode
+ def test_ui_init(self):
+ with subprocess.Popen(UPDATER) as proc:
+ time.sleep(5)
+ self.assertTrue(proc.poll() is None)
+ proc.terminate()
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/installer/updater/update_kernel.json b/installer/updater/update_kernel.json
new file mode 100644
index 0000000000..41dc595b00
--- /dev/null
+++ b/installer/updater/update_kernel.json
@@ -0,0 +1,7 @@
+{
+ "ota_url": "https://commadist.azureedge.net/neosupdate/ota-signed-3bd2b3bdd6a501569e00b8f12786d65e0fd2788c0dd238f8c986e3e2e504683a-kernel.zip",
+ "ota_hash": "3bd2b3bdd6a501569e00b8f12786d65e0fd2788c0dd238f8c986e3e2e504683a",
+ "recovery_url": "https://commadist.azureedge.net/neosupdate/recovery-97c27e6ed04ed6bb0608b845a2d4100912093f9380c3f2ba6b56bccd608e5f6e.img",
+ "recovery_len": 15861036,
+ "recovery_hash": "97c27e6ed04ed6bb0608b845a2d4100912093f9380c3f2ba6b56bccd608e5f6e"
+}
diff --git a/installer/updater/updater b/installer/updater/updater
index 15858eabb4..66047420c1 100755
Binary files a/installer/updater/updater and b/installer/updater/updater differ
diff --git a/installer/updater/updater.cc b/installer/updater/updater.cc
index a76be8b8fd..ca0b9270b8 100644
--- a/installer/updater/updater.cc
+++ b/installer/updater/updater.cc
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
#include
#include
@@ -33,10 +34,10 @@
#define USER_AGENT "NEOSUpdater-0.2"
-#define MANIFEST_URL_EON_STAGING "https://github.com/commaai/eon-neos/raw/master/update.staging.json"
-#define MANIFEST_URL_EON_LOCAL "http://192.168.5.1:8000/neosupdate/update.local.json"
-#define MANIFEST_URL_EON "https://github.com/commaai/eon-neos/raw/master/update.json"
-const char *manifest_url = MANIFEST_URL_EON;
+#define MANIFEST_URL_NEOS_STAGING "https://github.com/commaai/eon-neos/raw/master/update.staging.json"
+#define MANIFEST_URL_NEOS_LOCAL "http://192.168.5.1:8000/neosupdate/update.local.json"
+#define MANIFEST_URL_NEOS "https://github.com/commaai/eon-neos/raw/master/update.json"
+const char *manifest_url = MANIFEST_URL_NEOS;
#define RECOVERY_DEV "/dev/block/bootdevice/by-name/recovery"
#define RECOVERY_COMMAND "/cache/recovery/command"
@@ -96,7 +97,7 @@ std::string download_string(CURL *curl, std::string url) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 0);
curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(curl, CURLOPT_RESUME_FROM, 0);
@@ -149,6 +150,32 @@ static void start_settings_activity(const char* name) {
system(launch_cmd);
}
+bool is_settings_active() {
+ FILE *fp;
+ char sys_output[4096];
+
+ fp = popen("/bin/dumpsys window windows", "r");
+ if (fp == NULL) {
+ return false;
+ }
+
+ bool active = false;
+ while (fgets(sys_output, sizeof(sys_output), fp) != NULL) {
+ if (strstr(sys_output, "mCurrentFocus=null") != NULL) {
+ break;
+ }
+
+ if (strstr(sys_output, "mCurrentFocus=Window") != NULL) {
+ active = true;
+ break;
+ }
+ }
+
+ pclose(fp);
+
+ return active;
+}
+
struct Updater {
bool do_exit = false;
@@ -166,7 +193,6 @@ struct Updater {
std::mutex lock;
- // i hate state machines give me coroutines already
enum UpdateState {
CONFIRMATION,
LOW_BATTERY,
@@ -190,9 +216,15 @@ struct Updater {
int b_x, b_w, b_y, b_h;
int balt_x;
+ // download stage writes these for the installation stage
+ int recovery_len;
+ std::string recovery_hash;
+ std::string recovery_fn;
+ std::string ota_fn;
+
CURL *curl = NULL;
- Updater() {
+ void ui_init() {
touch_init(&touch);
fb = framebuffer_init("updater", 0x00001000, false,
@@ -218,7 +250,6 @@ struct Updater {
b_h = 220;
state = CONFIRMATION;
-
}
int download_file_xferinfo(curl_off_t dltotal, curl_off_t dlno,
@@ -251,7 +282,7 @@ struct Updater {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 0);
curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(curl, CURLOPT_RESUME_FROM, resume_from);
@@ -319,92 +350,78 @@ struct Updater {
state = RUNNING;
}
- std::string stage_download(std::string url, std::string hash, std::string name) {
+ std::string download(std::string url, std::string hash, std::string name) {
std::string out_fn = UPDATE_DIR "/" + util::base_name(url);
- set_progress("Downloading " + name + "...");
- bool r = download_file(url, out_fn);
- if (!r) {
- set_error("failed to download " + name);
- return "";
+ // start or resume downloading if hash doesn't match
+ std::string fn_hash = sha256_file(out_fn);
+ if (hash.compare(fn_hash) != 0) {
+ set_progress("Downloading " + name + "...");
+ bool r = download_file(url, out_fn);
+ if (!r) {
+ set_error("failed to download " + name);
+ unlink(out_fn.c_str());
+ return "";
+ }
+ fn_hash = sha256_file(out_fn);
}
set_progress("Verifying " + name + "...");
- std::string fn_hash = sha256_file(out_fn);
printf("got %s hash: %s\n", name.c_str(), hash.c_str());
if (fn_hash != hash) {
set_error(name + " was corrupt");
unlink(out_fn.c_str());
return "";
}
-
return out_fn;
}
- void run_stages() {
+ bool download_stage() {
curl = curl_easy_init();
assert(curl);
- if (!check_battery()) {
- set_battery_low();
- int battery_cap = battery_capacity();
- while(battery_cap < min_battery_cap) {
- battery_cap = battery_capacity();
- battery_cap_text = std::to_string(battery_cap);
- usleep(1000000);
- }
- set_running();
- }
+ // ** quick checks before download **
if (!check_space()) {
set_error("2GB of free space required to update");
- return;
+ return false;
}
mkdir(UPDATE_DIR, 0777);
- const int EON = (access("/EON", F_OK) != -1);
-
set_progress("Finding latest version...");
- std::string manifest_s;
- if (EON) {
- manifest_s = download_string(curl, manifest_url);
- } else {
- // don't update NEO
- exit(0);
- }
-
+ std::string manifest_s = download_string(curl, manifest_url);
printf("manifest: %s\n", manifest_s.c_str());
std::string err;
auto manifest = json11::Json::parse(manifest_s, err);
if (manifest.is_null() || !err.empty()) {
set_error("failed to load update manifest");
- return;
+ return false;
}
std::string ota_url = manifest["ota_url"].string_value();
std::string ota_hash = manifest["ota_hash"].string_value();
std::string recovery_url = manifest["recovery_url"].string_value();
- std::string recovery_hash = manifest["recovery_hash"].string_value();
- int recovery_len = manifest["recovery_len"].int_value();
+ recovery_hash = manifest["recovery_hash"].string_value();
+ recovery_len = manifest["recovery_len"].int_value();
// std::string installer_url = manifest["installer_url"].string_value();
// std::string installer_hash = manifest["installer_hash"].string_value();
if (ota_url.empty() || ota_hash.empty()) {
set_error("invalid update manifest");
- return;
+ return false;
}
- // std::string installer_fn = stage_download(installer_url, installer_hash, "installer");
+ // std::string installer_fn = download(installer_url, installer_hash, "installer");
// if (installer_fn.empty()) {
// //error'd
// return;
// }
- std::string recovery_fn;
+ // ** handle recovery download **
if (recovery_url.empty() || recovery_hash.empty() || recovery_len == 0) {
set_progress("Skipping recovery flash...");
} else {
@@ -414,20 +431,50 @@ struct Updater {
printf("existing recovery hash: %s\n", existing_recovery_hash.c_str());
if (existing_recovery_hash != recovery_hash) {
- recovery_fn = stage_download(recovery_url, recovery_hash, "recovery");
+ recovery_fn = download(recovery_url, recovery_hash, "recovery");
if (recovery_fn.empty()) {
// error'd
- return;
+ return false;
}
}
}
- std::string ota_fn = stage_download(ota_url, ota_hash, "update");
+ // ** handle ota download **
+ ota_fn = download(ota_url, ota_hash, "update");
if (ota_fn.empty()) {
//error'd
+ return false;
+ }
+
+ // download sucessful
+ return true;
+ }
+
+ // thread that handles downloading and installing the update
+ void run_stages() {
+ printf("run_stages start\n");
+
+
+ // ** download update **
+
+ if (!check_battery()) {
+ set_battery_low();
+ int battery_cap = battery_capacity();
+ while(battery_cap < min_battery_cap) {
+ battery_cap = battery_capacity();
+ battery_cap_text = std::to_string(battery_cap);
+ usleep(1000000);
+ }
+ set_running();
+ }
+
+ bool sucess = download_stage();
+ if (!sucess) {
return;
}
+ // ** install update **
+
if (!check_battery()) {
set_battery_low();
int battery_cap = battery_capacity();
@@ -601,7 +648,7 @@ struct Updater {
int powerprompt_y = 312;
nvgFontFace(vg, "opensans_regular");
nvgFontSize(vg, 64.0f);
- nvgText(vg, fb_w/2, 740, "Ensure EON is connected to power.", NULL);
+ nvgText(vg, fb_w/2, 740, "Ensure your device remains connected to a power source.", NULL);
NVGpaint paint = nvgBoxGradient(
vg, progress_x + 1, progress_y + 1,
@@ -657,9 +704,7 @@ struct Updater {
void ui_update() {
std::lock_guard guard(lock);
- switch (state) {
- case ERROR:
- case CONFIRMATION: {
+ if (state == ERROR || state == CONFIRMATION) {
int touch_x = -1, touch_y = -1;
int res = touch_poll(&touch, &touch_x, &touch_y, 0);
if (res == 1 && !is_settings_active()) {
@@ -678,13 +723,11 @@ struct Updater {
}
}
}
- default:
- break;
- }
}
-
void go() {
+ ui_init();
+
while (!do_exit) {
ui_update();
@@ -718,51 +761,37 @@ struct Updater {
update_thread_handle.join();
}
+ // reboot
system("service call power 16 i32 0 i32 0 i32 1");
}
- bool is_settings_active() {
- FILE *fp;
- char sys_output[4096];
-
- fp = popen("/bin/dumpsys window windows", "r");
- if (fp == NULL) {
- return false;
- }
-
- bool active = false;
- while (fgets(sys_output, sizeof(sys_output), fp) != NULL) {
- if (strstr(sys_output, "mCurrentFocus=null") != NULL) {
- break;
- }
-
- if (strstr(sys_output, "mCurrentFocus=Window") != NULL) {
- active = true;
- break;
- }
- }
-
- pclose(fp);
-
- return active;
- }
-
};
}
+
int main(int argc, char *argv[]) {
+ bool background_cache = false;
if (argc > 1) {
if (strcmp(argv[1], "local") == 0) {
- manifest_url = MANIFEST_URL_EON_LOCAL;
+ manifest_url = MANIFEST_URL_NEOS_LOCAL;
} else if (strcmp(argv[1], "staging") == 0) {
- manifest_url = MANIFEST_URL_EON_STAGING;
+ manifest_url = MANIFEST_URL_NEOS_STAGING;
+ } else if (strcmp(argv[1], "bgcache") == 0) {
+ manifest_url = argv[2];
+ background_cache = true;
} else {
manifest_url = argv[1];
}
}
+
printf("updating from %s\n", manifest_url);
Updater updater;
- updater.go();
- return 0;
+ int err = 0;
+ if (background_cache) {
+ err = !updater.download_stage();
+ } else {
+ updater.go();
+ }
+ return err;
}
diff --git a/laika_repo b/laika_repo
index d172b27f4f..765c6584c3 160000
--- a/laika_repo
+++ b/laika_repo
@@ -1 +1 @@
-Subproject commit d172b27f4f346e642802a4c7cbf14405a4161d35
+Subproject commit 765c6584c3d7f27e1af0f1180cc29766d5319f09
diff --git a/launch_chffrplus.sh b/launch_chffrplus.sh
index f88f6fb7d1..af5483562d 100755
--- a/launch_chffrplus.sh
+++ b/launch_chffrplus.sh
@@ -1,25 +1,20 @@
#!/usr/bin/bash
-export OMP_NUM_THREADS=1
-export MKL_NUM_THREADS=1
-export NUMEXPR_NUM_THREADS=1
-export OPENBLAS_NUM_THREADS=1
-export VECLIB_MAXIMUM_THREADS=1
-
if [ -z "$BASEDIR" ]; then
BASEDIR="/data/openpilot"
fi
-if [ -z "$PASSIVE" ]; then
- export PASSIVE="1"
-fi
+source "$BASEDIR/launch_env.sh"
-STAGING_ROOT="/data/safe_staging"
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
function launch {
# Wifi scan
wpa_cli IFNAME=wlan0 SCAN
+ # Remove orphaned git lock if it exists on boot
+ [ -f "$DIR/.git/index.lock" ] && rm -f $DIR/.git/index.lock
+
# Check to see if there's a valid overlay-based update available. Conditions
# are as follows:
#
@@ -41,11 +36,15 @@ function launch {
mv $BASEDIR /data/safe_staging/old_openpilot
mv "${STAGING_ROOT}/finalized" $BASEDIR
+ cd $BASEDIR
- # The mv changed our working directory to /data/safe_staging/old_openpilot
- cd "${BASEDIR}"
+ # Partial mitigation for symlink-related filesystem corruption
+ # Ensure all files match the repo versions after update
+ git reset --hard
+ git submodule foreach --recursive git reset --hard
echo "Restarting launch script ${LAUNCHER_LOCATION}"
+ unset REQUIRED_NEOS_VERSION
exec "${LAUNCHER_LOCATION}"
else
echo "openpilot backup found, not updating"
@@ -55,36 +54,57 @@ function launch {
fi
fi
- # no cpu rationing for now
- echo 0-3 > /dev/cpuset/background/cpus
- echo 0-3 > /dev/cpuset/system-background/cpus
- echo 0-3 > /dev/cpuset/foreground/boost/cpus
- echo 0-3 > /dev/cpuset/foreground/cpus
- echo 0-3 > /dev/cpuset/android/cpus
-
- # change interrupt affinity
- echo 3 > /proc/irq/6/smp_affinity_list # MDSS
- echo 1 > /proc/irq/78/smp_affinity_list # Modem, can potentially lock up
- echo 2 > /proc/irq/733/smp_affinity_list # USB
- echo 2 > /proc/irq/736/smp_affinity_list # USB
-
- DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-
- # Remove old NEOS update file
- # TODO: move this code to the updater
- if [ -d /data/neoupdate ]; then
- rm -rf /data/neoupdate
- fi
+ # Android and other system processes are not permitted to run on CPU 3
+ # NEOS installed app processes can run anywhere
+ echo 0-2 > /dev/cpuset/background/cpus
+ echo 0-2 > /dev/cpuset/system-background/cpus
+ [ -d "/dev/cpuset/foreground/boost/cpus" ] && echo 0-2 > /dev/cpuset/foreground/boost/cpus # Not present in < NEOS 15
+ echo 0-2 > /dev/cpuset/foreground/cpus
+ echo 0-2 > /dev/cpuset/android/cpus
+ echo 0-3 > /dev/cpuset/app/cpus
+
+ # Collect RIL and other possibly long-running I/O interrupts onto CPU 1
+ echo 1 > /proc/irq/78/smp_affinity_list # qcom,smd-modem (LTE radio)
+ echo 1 > /proc/irq/33/smp_affinity_list # ufshcd (flash storage)
+ echo 1 > /proc/irq/35/smp_affinity_list # wifi (wlan_pci)
+ # USB traffic needs realtime handling on cpu 3
+ [ -d "/proc/irq/733" ] && echo 3 > /proc/irq/733/smp_affinity_list # USB for LeEco
+ [ -d "/proc/irq/736" ] && echo 3 > /proc/irq/736/smp_affinity_list # USB for OP3T
+
# Check for NEOS update
- if [ $(< /VERSION) != "14" ]; then
+ if [ $(< /VERSION) != "$REQUIRED_NEOS_VERSION" ]; then
if [ -f "$DIR/scripts/continue.sh" ]; then
cp "$DIR/scripts/continue.sh" "/data/data/com.termux/files/continue.sh"
fi
+ if [ ! -f "$BASEDIR/prebuilt" ]; then
+ # Clean old build products, but preserve the scons cache
+ cd $DIR
+ scons --clean
+ git clean -xdf
+ git submodule foreach --recursive git clean -xdf
+ fi
+
"$DIR/installer/updater/updater" "file://$DIR/installer/updater/update.json"
+ else
+ if [[ $(uname -v) == "#1 SMP PREEMPT Wed Jun 10 12:40:53 PDT 2020" ]]; then
+ "$DIR/installer/updater/updater" "file://$DIR/installer/updater/update_kernel.json"
+ fi
fi
+ # One-time fix for a subset of OP3T with gyro orientation offsets.
+ # Remove and regenerate qcom sensor registry. Only done on OP3T mainboards.
+ # Performed exactly once. The old registry is preserved just-in-case, and
+ # doubles as a flag denoting we've already done the reset.
+ # TODO: we should really grow per-platform detect and setup routines
+ if ! $(grep -q "letv" /proc/cmdline) && [ ! -f "/persist/comma/op3t-sns-reg-backup" ]; then
+ echo "Performing OP3T sensor registry reset"
+ mv /persist/sensors/sns.reg /persist/comma/op3t-sns-reg-backup &&
+ rm -f /persist/sensors/sensors_settings /persist/sensors/error_log /persist/sensors/gyro_sensitity_cal &&
+ echo "restart" > /sys/kernel/debug/msm_subsys/slpi &&
+ sleep 5 # Give Android sensor subsystem a moment to recover
+ fi
# handle pythonpath
ln -sfn $(pwd) /data/pythonpath
diff --git a/launch_env.sh b/launch_env.sh
new file mode 100755
index 0000000000..9a86d315ce
--- /dev/null
+++ b/launch_env.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/bash
+
+export OMP_NUM_THREADS=1
+export MKL_NUM_THREADS=1
+export NUMEXPR_NUM_THREADS=1
+export OPENBLAS_NUM_THREADS=1
+export VECLIB_MAXIMUM_THREADS=1
+
+if [ -z "$REQUIRED_NEOS_VERSION" ]; then
+ export REQUIRED_NEOS_VERSION="14"
+fi
+
+if [ -z "$PASSIVE" ]; then
+ export PASSIVE="1"
+fi
+
+export STAGING_ROOT="/data/safe_staging"
diff --git a/models/dmonitoring_model.current b/models/dmonitoring_model.current
index 9c95aff333..b0026f152a 100644
--- a/models/dmonitoring_model.current
+++ b/models/dmonitoring_model.current
@@ -1 +1 @@
-43221d85-46fd-40b9-bff0-2b1b18a86b07
\ No newline at end of file
+e96f9be6-5741-42ea-bdcd-0be6515b4230
\ No newline at end of file
diff --git a/models/dmonitoring_model.keras b/models/dmonitoring_model.keras
index 9a835302ec..c3d58f6fc7 100644
--- a/models/dmonitoring_model.keras
+++ b/models/dmonitoring_model.keras
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5c39a2096f7058541b5339ec36bc4c468955e67285078080ed6d8802fed06c1d
-size 814176
+oid sha256:09aa11a17a5a8173e231071898c499f9ea632e6e64285586122828b1bbc70d41
+size 4165968
diff --git a/models/dmonitoring_model_q.dlc b/models/dmonitoring_model_q.dlc
index fc990411e9..558b359bfa 100644
--- a/models/dmonitoring_model_q.dlc
+++ b/models/dmonitoring_model_q.dlc
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:29504dfd101ba2a0b48550fac2f86f9d0b8d1245af3d2d8d658247b4a73077a2
-size 230121
+oid sha256:beecf140ddc5da96cbdae3b869ebb3f5453dcd8e61e09d7d079c91e006b6df98
+size 1134208
diff --git a/mypy.ini b/mypy.ini
new file mode 100644
index 0000000000..66b82bd5df
--- /dev/null
+++ b/mypy.ini
@@ -0,0 +1,4 @@
+[mypy]
+python_version = 3.8
+ignore_missing_imports = True
+
diff --git a/opendbc b/opendbc
index 45c0d9ecce..b7cf1a67bc 160000
--- a/opendbc
+++ b/opendbc
@@ -1 +1 @@
-Subproject commit 45c0d9ecce255e028163539e22e9a169735de69d
+Subproject commit b7cf1a67bc71b674e6793ba1f2fff5d29fee1e6b
diff --git a/panda b/panda
index 6b19fa4961..ecef0a19d0 160000
--- a/panda
+++ b/panda
@@ -1 +1 @@
-Subproject commit 6b19fa4961d5dc6e6ea77987eb3a99ce28b0f5cd
+Subproject commit ecef0a19d0f72d8fd3151593b7bd1a112d5f63e2
diff --git a/pyextra/logentries/__init__.py b/pyextra/logentries/__init__.py
deleted file mode 100644
index b64e423b8b..0000000000
--- a/pyextra/logentries/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .utils import LogentriesHandler
diff --git a/pyextra/logentries/helpers.py b/pyextra/logentries/helpers.py
deleted file mode 100644
index bec676e22a..0000000000
--- a/pyextra/logentries/helpers.py
+++ /dev/null
@@ -1,49 +0,0 @@
-
-""" This file contains some helpers methods in both Python2 and 3 """
-import sys
-import re
-
-if sys.version < '3':
- # Python2.x imports
- import Queue
- import codecs
-else:
- # Python 3.x imports
- import queue
-
-
-def check_token(token):
- """ Checks if the given token is a valid UUID."""
- valid = re.compile(r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-"
- r"[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$")
-
- return valid.match(token)
-
-# We need to do some things different pending if its Python 2.x or 3.x
-if sys.version < '3':
- def to_unicode(ch):
- return codecs.unicode_escape_decode(ch)[0]
-
- def is_unicode(ch):
- return isinstance(ch, unicode)
-
- def create_unicode(ch):
- try:
- return unicode(ch, 'utf-8')
- except UnicodeDecodeError as e:
- return str(e)
-
- def create_queue(max_size):
- return Queue.Queue(max_size)
-else:
- def to_unicode(ch):
- return ch
-
- def is_unicode(ch):
- return isinstance(ch, str)
-
- def create_unicode(ch):
- return str(ch)
-
- def create_queue(max_size):
- return queue.Queue(max_size)
diff --git a/pyextra/logentries/metrics.py b/pyextra/logentries/metrics.py
deleted file mode 100644
index 03ddb64374..0000000000
--- a/pyextra/logentries/metrics.py
+++ /dev/null
@@ -1,57 +0,0 @@
-from logentries import LogentriesHandler
-from threading import Lock
-from functools import wraps
-import logging
-import time
-import sys
-import psutil
-
-glob_time = 0
-glob_name = 0
-
-log = logging.getLogger('logentries')
-log.setLevel(logging.INFO)
-
-class Metric(object):
-
- def __init__(self, token):
- self._count = 0.0
- self._sum = 0.0
- self._lock = Lock()
- self.token = token
- handler = LogentriesHandler(token)
- log.addHandler(handler)
-
- def observe(self, amount):
- with self._lock:
- self._count += 1
- self._sum += amount
-
- def metric(self):
- '''Mesaure function execution time in seconds
- and forward it to Logentries'''
-
- class Timer(object):
-
- def __init__(self, summary):
- self._summary = summary
-
- def __enter__(self):
- self._start = time.time()
-
- def __exit__(self, typ, value, traceback):
- global glob_time
- self._summary.observe(max(time.time() - self._start, 0))
- glob_time = time.time()- self._start
- log.info("function_name=" + glob_name + " " + "execution_time=" + str(glob_time) + " " + "cpu=" + str(psutil.cpu_percent(interval=None)) + " " + "cpu_count=" + str(psutil.cpu_count())+ " " + "memory=" + str(psutil.virtual_memory()) )
-
- def __call__(self, f):
- @wraps(f)
- def wrapped(*args, **kwargs):
- with self:
- global glob_name
- glob_name = f.__name__
-
- return f(*args, **kwargs)
- return wrapped
- return Timer(self)
diff --git a/pyextra/logentries/utils.py b/pyextra/logentries/utils.py
deleted file mode 100644
index c17a1070cd..0000000000
--- a/pyextra/logentries/utils.py
+++ /dev/null
@@ -1,218 +0,0 @@
-# coding: utf-8
-# vim: set ts=4 sw=4 et:
-""" This file contains some utils for connecting to Logentries
- as well as storing logs in a queue and sending them."""
-
-VERSION = '2.0.7'
-
-from logentries import helpers as le_helpers
-
-import logging
-import threading
-import socket
-import random
-import time
-import sys
-
-import certifi
-
-
-# Size of the internal event queue
-QUEUE_SIZE = 32768
-# Logentries API server address
-LE_API_DEFAULT = "data.logentries.com"
-# Port number for token logging to Logentries API server
-LE_PORT_DEFAULT = 80
-LE_TLS_PORT_DEFAULT = 443
-# Minimal delay between attempts to reconnect in seconds
-MIN_DELAY = 0.1
-# Maximal delay between attempts to recconect in seconds
-MAX_DELAY = 10
-# Unicode Line separator character \u2028
-LINE_SEP = le_helpers.to_unicode('\u2028')
-
-
-# LE appender signature - used for debugging messages
-LE = "LE: "
-# Error message displayed when an incorrect Token has been detected
-INVALID_TOKEN = ("\n\nIt appears the LOGENTRIES_TOKEN "
- "parameter you entered is incorrect!\n\n")
-
-
-def dbg(msg):
- print(LE + msg)
-
-
-class PlainTextSocketAppender(threading.Thread):
- def __init__(self, verbose=True, le_api=LE_API_DEFAULT, le_port=LE_PORT_DEFAULT, le_tls_port=LE_TLS_PORT_DEFAULT):
- threading.Thread.__init__(self)
-
- # Logentries API server address
- self.le_api = le_api
-
- # Port number for token logging to Logentries API server
- self.le_port = le_port
- self.le_tls_port = le_tls_port
-
- self.daemon = True
- self.verbose = verbose
- self._conn = None
- self._queue = le_helpers.create_queue(QUEUE_SIZE)
-
- def empty(self):
- return self._queue.empty()
-
- def open_connection(self):
- self._conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self._conn.connect((self.le_api, self.le_port))
-
- def reopen_connection(self):
- self.close_connection()
-
- root_delay = MIN_DELAY
- while True:
- try:
- self.open_connection()
- return
- except Exception:
- if self.verbose:
- dbg("Unable to connect to Logentries")
-
- root_delay *= 2
- if(root_delay > MAX_DELAY):
- root_delay = MAX_DELAY
-
- wait_for = root_delay + random.uniform(0, root_delay)
-
- try:
- time.sleep(wait_for)
- except KeyboardInterrupt:
- raise
-
- def close_connection(self):
- if self._conn is not None:
- self._conn.close()
-
- def run(self):
- try:
- # Open connection
- self.reopen_connection()
-
- # Send data in queue
- while True:
- # Take data from queue
- data = self._queue.get(block=True)
-
- # Replace newlines with Unicode line separator
- # for multi-line events
- if not le_helpers.is_unicode(data):
- multiline = le_helpers.create_unicode(data).replace(
- '\n', LINE_SEP)
- else:
- multiline = data.replace('\n', LINE_SEP)
- multiline += "\n"
- # Send data, reconnect if needed
- while True:
- try:
- self._conn.send(multiline.encode('utf-8'))
- except socket.error:
- self.reopen_connection()
- continue
- break
- except KeyboardInterrupt:
- if self.verbose:
- dbg("Logentries asynchronous socket client interrupted")
-
- self.close_connection()
-
-SocketAppender = PlainTextSocketAppender
-
-try:
- import ssl
- ssl_enabled = True
-except ImportError: # for systems without TLS support.
- ssl_enabled = False
- dbg("Unable to import ssl module. Will send over port 80.")
-else:
- class TLSSocketAppender(PlainTextSocketAppender):
-
- def open_connection(self):
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock = ssl.wrap_socket(
- sock=sock,
- keyfile=None,
- certfile=None,
- server_side=False,
- cert_reqs=ssl.CERT_REQUIRED,
- ssl_version=getattr(
- ssl,
- 'PROTOCOL_TLSv1_2',
- ssl.PROTOCOL_TLSv1
- ),
- ca_certs=certifi.where(),
- do_handshake_on_connect=True,
- suppress_ragged_eofs=True,
- )
-
- sock.connect((self.le_api, self.le_tls_port))
- self._conn = sock
-
-
-class LogentriesHandler(logging.Handler):
- def __init__(self, token, use_tls=True, verbose=True, format=None, le_api=LE_API_DEFAULT, le_port=LE_PORT_DEFAULT, le_tls_port=LE_TLS_PORT_DEFAULT):
- logging.Handler.__init__(self)
- self.token = token
- self.good_config = True
- self.verbose = verbose
- # give the socket 10 seconds to flush,
- # otherwise drop logs
- self.timeout = 10
- if not le_helpers.check_token(token):
- if self.verbose:
- dbg(INVALID_TOKEN)
- self.good_config = False
- if format is None:
- format = logging.Formatter('%(asctime)s : %(levelname)s, %(message)s',
- '%a %b %d %H:%M:%S %Z %Y')
- self.setFormatter(format)
- self.setLevel(logging.DEBUG)
- if use_tls and ssl_enabled:
- self._thread = TLSSocketAppender(verbose=verbose, le_api=le_api, le_port=le_port, le_tls_port=le_tls_port)
- else:
- self._thread = SocketAppender(verbose=verbose, le_api=le_api, le_port=le_port, le_tls_port=le_tls_port)
-
- def flush(self):
- # wait for all queued logs to be send
- now = time.time()
- while not self._thread.empty():
- time.sleep(0.2)
- if time.time() - now > self.timeout:
- break
-
- def emit_raw(self, msg):
- if self.good_config and not self._thread.is_alive():
- try:
- self._thread.start()
- if self.verbose:
- dbg("Starting Logentries Asynchronous Socket Appender")
- except RuntimeError: # It's already started.
- pass
-
- msg = self.token + msg
- try:
- self._thread._queue.put_nowait(msg)
- except Exception:
- # Queue is full, try to remove the oldest message and put again
- try:
- self._thread._queue.get_nowait()
- self._thread._queue.put_nowait(msg)
- except Exception:
- # Race condition, no need for any action here
- pass
-
- def emit(self, record):
- msg = self.format(record).rstrip('\n')
- self.emit_raw(msg)
-
- def close(self):
- logging.Handler.close(self)
diff --git a/pylint_openpilot.sh b/pylint_openpilot.sh
deleted file mode 100755
index 910c5cd09a..0000000000
--- a/pylint_openpilot.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env bash
-
-python3 -m pylint --disable=R,C,W $(eval echo <(find cereal) <(find opendbc) $(cat release/files_common release/files_common | tr '\n' ' ') | tr ' ' '\n' | grep "\.py$")
-
-exit_status=$?
-(( res = exit_status & 3 ))
-
-if [[ $res != 0 ]]; then
- echo "Pylint found errors in the code. Please fix and try again"
- exit 1
-fi
diff --git a/rednose_repo b/rednose_repo
index d3a79c6a42..2e556b8219 160000
--- a/rednose_repo
+++ b/rednose_repo
@@ -1 +1 @@
-Subproject commit d3a79c6a421b4eec952eeb8d1546a4c3c3ff030e
+Subproject commit 2e556b8219185708ed974a4b6502796607d7ce0d
diff --git a/release/build_devel.sh b/release/build_devel.sh
index 26f92445a3..8e2e7ce7f6 100755
--- a/release/build_devel.sh
+++ b/release/build_devel.sh
@@ -1,30 +1,4 @@
-#!/usr/bin/env bash
-set -e
-
-mkdir -p /dev/shm
-chmod 777 /dev/shm
-
-# Write cpuset
-echo $$ > /dev/cpuset/app/tasks
-echo $PPID > /dev/cpuset/app/tasks
-
-
-add_subtree() {
- echo "[-] adding $2 subtree T=$SECONDS"
- if [ -d "$2" ]; then
- if git subtree pull --prefix "$2" https://github.com/commaai/"$1".git "$3" --squash -m "Merge $2 subtree"; then
- echo "git subtree pull succeeds"
- else
- echo "git subtree pull failed, fixing"
- git merge --abort || true
- git rm -r $2
- git commit -m "Remove old $2 subtree"
- git subtree add --prefix "$2" https://github.com/commaai/"$1".git "$3" --squash
- fi
- else
- git subtree add --prefix "$2" https://github.com/commaai/"$1".git "$3" --squash
- fi
-}
+#!/usr/bin/bash -e
SOURCE_DIR=/data/openpilot_source
TARGET_DIR=/data/openpilot
@@ -35,17 +9,16 @@ export GIT_COMMITTER_NAME="Vehicle Researcher"
export GIT_COMMITTER_EMAIL="user@comma.ai"
export GIT_AUTHOR_NAME="Vehicle Researcher"
export GIT_AUTHOR_EMAIL="user@comma.ai"
-export GIT_SSH_COMMAND="ssh -i /tmp/deploy_key"
+export GIT_SSH_COMMAND="ssh -i /data/gitkey"
echo "[-] Setting up repo T=$SECONDS"
if [ ! -d "$TARGET_DIR" ]; then
- mkdir -p $TARGET_DIR
- cd $TARGET_DIR
- git init
- git remote add origin git@github.com:commaai/openpilot.git
+ mkdir -p $TARGET_DIR
+ cd $TARGET_DIR
+ git init
+ git remote add origin git@github.com:commaai/openpilot.git
fi
-
echo "[-] fetching public T=$SECONDS"
cd $TARGET_DIR
git prune || true
@@ -55,27 +28,15 @@ echo "[-] bringing master-ci and devel in sync T=$SECONDS"
git fetch origin master-ci
git fetch origin devel
-git checkout --track origin/master-ci || true
+git checkout -f --track origin/master-ci
git reset --hard master-ci
git checkout master-ci
git reset --hard origin/devel
git clean -xdf
-# subtrees to make updates more reliable. updating them needs a clean tree
-add_subtree "cereal" "cereal" master
-add_subtree "panda" "panda" master
-add_subtree "opendbc" "opendbc" master
-add_subtree "openpilot-pyextra" "pyextra" master
-
-# leave .git alone
+# remove everything except .git
echo "[-] erasing old openpilot T=$SECONDS"
-rm -rf $TARGET_DIR/* $TARGET_DIR/.gitmodules
-
-# delete dotfiles in root
-find . -maxdepth 1 -type f -delete
-
-# dont delete our subtrees
-git checkout -- cereal panda opendbc pyextra
+find . -maxdepth 1 -not -path './.git' -not -name '.' -not -name '..' -exec rm -rf '{}' \;
# reset tree and get version
cd $SOURCE_DIR
@@ -103,15 +64,6 @@ git commit -a -m "openpilot v$VERSION release"
# Run build
SCONS_CACHE=1 scons -j3
-echo "[-] testing openpilot T=$SECONDS"
-echo -n "0" > /data/params/d/Passive
-echo -n "0.2.0" > /data/params/d/CompletedTrainingVersion
-echo -n "1" > /data/params/d/HasCompletedSetup
-echo -n "1" > /data/params/d/CommunityFeaturesToggle
-
-PYTHONPATH="$TARGET_DIR:$TARGET_DIR/pyextra" nosetests -s selfdrive/test/test_openpilot.py
-PYTHONPATH="$TARGET_DIR:$TARGET_DIR/pyextra" GET_CPU_USAGE=1 selfdrive/manager.py
-
echo "[-] testing panda build T=$SECONDS"
pushd panda/board/
make bin
@@ -122,15 +74,10 @@ pushd panda/board/pedal
make obj/comma.bin
popd
-if [ ! -z "$PUSH" ]; then
- echo "[-] Pushing to $PUSH T=$SECONDS"
- git push -f origin master-ci:$PUSH
+if [ ! -z "$CI_PUSH" ]; then
+ echo "[-] Pushing to $CI_PUSH T=$SECONDS"
+ git remote set-url origin git@github.com:commaai/openpilot.git
+ git push -f origin master-ci:$CI_PUSH
fi
-echo "[-] done pushing T=$SECONDS"
-
-# reset version
-cd $SOURCE_DIR
-git checkout -- selfdrive/common/version.h
-
echo "[-] done T=$SECONDS"
diff --git a/release/build_release2.sh b/release/build_release2.sh
index 8e1466830b..9378bb723b 100755
--- a/release/build_release2.sh
+++ b/release/build_release2.sh
@@ -8,24 +8,32 @@ export GIT_AUTHOR_EMAIL="user@comma.ai"
export GIT_SSH_COMMAND="ssh -i /data/gitkey"
-# Create folders
-rm -rf /data/openpilot
-mkdir -p /data/openpilot
-cd /data/openpilot
-
-# Create git repo
-git init
-git remote add origin git@github.com:commaai/openpilot.git
-git fetch origin devel
+# set CLEAN to build outside of CI
+if [ ! -z "$CLEAN" ]; then
+ # Create folders
+ rm -rf /data/openpilot
+ mkdir -p /data/openpilot
+ cd /data/openpilot
+
+ # Create git repo
+ git init
+ git remote add origin git@github.com:commaai/openpilot.git
+ git fetch origin devel-staging
+else
+ cd /data/openpilot
+ git clean -xdf
+ git branch -D release2-staging || true
+fi
+
git fetch origin release2-staging
git fetch origin dashcam-staging
-# Checkout devel
-#git checkout origin/devel
-#git clean -xdf
-
# Create release2 with no history
-git checkout --orphan release2-staging origin/devel
+if [ ! -z "$CLEAN" ]; then
+ git checkout --orphan release2-staging origin/devel-staging
+else
+ git checkout --orphan release2-staging
+fi
VERSION=$(cat selfdrive/common/version.h | awk -F\" '{print $2}')
git commit -m "openpilot v$VERSION"
@@ -41,14 +49,24 @@ rm -rf /data/openpilot/pandaextra
popd
# Build stuff
-ln -sf /data/openpilot /data/pythonpath
+ln -sfn /data/openpilot /data/pythonpath
export PYTHONPATH="/data/openpilot:/data/openpilot/pyextra"
SCONS_CACHE=1 scons -j3
+
+# Run tests
nosetests -s selfdrive/test/test_openpilot.py
+selfdrive/car/tests/test_car_interfaces.py
# Cleanup
+find . -name '*.a' -delete
+find . -name '*.o' -delete
+find . -name '*.os' -delete
find . -name '*.pyc' -delete
-rm .sconsign.dblite
+find . -name '__pycache__' -delete
+rm -rf .sconsign.dblite Jenkinsfile release/
+
+# Restore phonelibs
+git checkout phonelibs/
# Mark as prebuilt release
touch prebuilt
@@ -57,11 +75,18 @@ touch prebuilt
git add -f .
git commit --amend -m "openpilot v$VERSION"
-# Push to release2-staging
-git push -f origin release2-staging
+# Print committed files that are normally gitignored
+#git status --ignored
+
+if [ ! -z "$PUSH" ]; then
+ git remote set-url origin git@github.com:commaai/openpilot.git
+
+ # Push to release2-staging
+ git push -f origin release2-staging
-# Create dashcam release
-git rm selfdrive/car/*/carcontroller.py
+ # Create dashcam release
+ git rm selfdrive/car/*/carcontroller.py
-git commit -m "create dashcam release from release2"
-git push -f origin release2-staging:dashcam-staging
+ git commit -m "create dashcam release from release2"
+ git push -f origin release2-staging:dashcam-staging
+fi
diff --git a/release/files_common b/release/files_common
index 1ca68db684..3bff234eab 100644
--- a/release/files_common
+++ b/release/files_common
@@ -1,18 +1,17 @@
-README.md
-SAFETY.md
-
-codecov.yml
-lgtm.yml
-
.gitignore
LICENSE
+launch.sh
+launch_env.sh
launch_chffrplus.sh
launch_openpilot.sh
+Jenkinsfile
+SConstruct
+
CONTRIBUTING.md
+README.md
RELEASES.md
-
-SConstruct
+SAFETY.md
apk/ai.comma*.apk
@@ -29,7 +28,6 @@ common/numpy_fast.py
common/params.py
common/xattr.py
common/profiler.py
-common/testing.py
common/basedir.py
common/filter_simple.py
common/stat_live.py
@@ -39,23 +37,32 @@ common/cython_hacks.py
common/apk.py
common/SConscript
common/common_pyx_setup.py
-common/manager_helpers.py
common/kalman/.gitignore
common/kalman/*
-common/kalman/tests/*
common/transformations/__init__.py
common/transformations/camera.py
-common/transformations/coordinates.py
common/transformations/model.py
+
+common/transformations/SConscript
+common/transformations/setup.py
+common/transformations/coordinates.py
+common/transformations/coordinates.cc
+common/transformations/coordinates.hpp
common/transformations/orientation.py
+common/transformations/orientation.cc
+common/transformations/orientation.hpp
+common/transformations/transformations.pxd
+common/transformations/transformations.pyx
common/api/__init__.py
models/supercombo.dlc
models/dmonitoring_model_q.dlc
+release/build_release2.sh
+
selfdrive/version.py
selfdrive/__init__.py
@@ -73,8 +80,6 @@ selfdrive/updated.py
selfdrive/athena/__init__.py
selfdrive/athena/athenad.py
selfdrive/athena/manage_athenad.py
-selfdrive/athena/test.py
-selfdrive/athena/test_helpers.py
selfdrive/boardd/.gitignore
selfdrive/boardd/SConscript
@@ -84,7 +89,10 @@ selfdrive/boardd/boardd.py
selfdrive/boardd/boardd_api_impl.pyx
selfdrive/boardd/boardd_setup.py
selfdrive/boardd/can_list_to_can_capnp.cc
-selfdrive/boardd/tests/**
+selfdrive/boardd/panda.cc
+selfdrive/boardd/panda.h
+selfdrive/boardd/pigeon.cc
+selfdrive/boardd/pigeon.h
selfdrive/car/__init__.py
selfdrive/car/car_helpers.py
@@ -93,6 +101,8 @@ selfdrive/car/interfaces.py
selfdrive/car/vin.py
selfdrive/car/fw_versions.py
selfdrive/car/isotp_parallel_query.py
+selfdrive/car/tests/__init__.py
+selfdrive/car/tests/test_car_interfaces.py
selfdrive/car/chrysler/__init__.py
selfdrive/car/chrysler/carstate.py
selfdrive/car/chrysler/interface.py
@@ -100,7 +110,6 @@ selfdrive/car/chrysler/radar_interface.py
selfdrive/car/chrysler/values.py
selfdrive/car/chrysler/carcontroller.py
selfdrive/car/chrysler/chryslercan.py
-selfdrive/car/chrysler/test_chryslercan.py
selfdrive/car/honda/__init__.py
selfdrive/car/honda/carstate.py
selfdrive/car/honda/interface.py
@@ -122,6 +131,13 @@ selfdrive/car/toyota/radar_interface.py
selfdrive/car/toyota/values.py
selfdrive/car/toyota/carcontroller.py
selfdrive/car/toyota/toyotacan.py
+selfdrive/car/nissan/__init__.py
+selfdrive/car/nissan/carcontroller.py
+selfdrive/car/nissan/carstate.py
+selfdrive/car/nissan/interface.py
+selfdrive/car/nissan/nissancan.py
+selfdrive/car/nissan/radar_interface.py
+selfdrive/car/nissan/values.py
selfdrive/car/volkswagen/__init__.py
selfdrive/car/volkswagen/carstate.py
selfdrive/car/volkswagen/interface.py
@@ -150,13 +166,19 @@ selfdrive/car/subaru/radar_interface.py
selfdrive/car/subaru/values.py
selfdrive/car/subaru/carcontroller.py
selfdrive/car/subaru/subarucan.py
+selfdrive/car/mazda/__init__.py
+selfdrive/car/mazda/carstate.py
+selfdrive/car/mazda/interface.py
+selfdrive/car/mazda/radar_interface.py
+selfdrive/car/mazda/values.py
+selfdrive/car/mazda/carcontroller.py
+selfdrive/car/mazda/mazdacan.py
selfdrive/car/mock/*.py
selfdrive/clocksd/.gitignore
selfdrive/clocksd/SConscript
selfdrive/clocksd/clocksd.cc
-selfdrive/debug/mpc/*
selfdrive/debug/*.py
selfdrive/common/SConscript
@@ -176,7 +198,6 @@ selfdrive/common/util.[c,h]
selfdrive/common/efd.[c,h]
selfdrive/common/cqueue.[c,h]
selfdrive/common/clutil.[c,h]
-selfdrive/common/messaging.h
selfdrive/common/params.h
selfdrive/common/params.cc
selfdrive/common/mutex.h
@@ -192,20 +213,19 @@ selfdrive/common/visionimg.cc
selfdrive/common/visionimg.h
selfdrive/common/spinner.c
selfdrive/common/spinner.h
+selfdrive/common/gpio.cc
+selfdrive/common/gpio.h
selfdrive/controls/__init__.py
-selfdrive/controls/tests/*
selfdrive/controls/controlsd.py
selfdrive/controls/plannerd.py
selfdrive/controls/radard.py
-selfdrive/controls/dmonitoringd.py
selfdrive/controls/lib/__init__.py
selfdrive/controls/lib/alertmanager.py
selfdrive/controls/lib/alerts_offroad.json
selfdrive/controls/lib/events.py
selfdrive/controls/lib/drive_helpers.py
-selfdrive/controls/lib/driver_monitor.py
selfdrive/controls/lib/latcontrol_pid.py
selfdrive/controls/lib/latcontrol_indi.py
selfdrive/controls/lib/latcontrol_lqr.py
@@ -220,7 +240,6 @@ selfdrive/controls/lib/speed_smoother.py
selfdrive/controls/lib/fcw.py
selfdrive/controls/lib/long_mpc.py
selfdrive/controls/lib/long_mpc_model.py
-selfdrive/controls/lib/driverview.py
selfdrive/controls/lib/cluster/*
@@ -256,7 +275,6 @@ selfdrive/locationd/ubloxd_main.cc
selfdrive/locationd/ubloxd_test.cc
selfdrive/locationd/ublox_msg.cc
selfdrive/locationd/ublox_msg.h
-selfdrive/locationd/test/*.py
selfdrive/locationd/locationd.py
selfdrive/locationd/paramsd.py
@@ -269,12 +287,6 @@ selfdrive/locationd/models/constants.py
selfdrive/locationd/calibrationd.py
selfdrive/locationd/calibration_helpers.py
-selfdrive/locationd/locationd_yawrate.cc
-selfdrive/locationd/locationd_yawrate.h
-selfdrive/locationd/params_learner.cc
-selfdrive/locationd/params_learner.h
-selfdrive/locationd/paramsd.cc
-
selfdrive/logcatd/SConscript
selfdrive/logcatd/logcatd.cc
@@ -295,7 +307,6 @@ selfdrive/loggerd/__init__.py
selfdrive/loggerd/config.py
selfdrive/loggerd/uploader.py
selfdrive/loggerd/deleter.py
-selfdrive/loggerd/tests/*
selfdrive/sensord/SConscript
selfdrive/sensord/gpsd.cc
@@ -308,25 +319,14 @@ selfdrive/thermald/thermald.py
selfdrive/thermald/power_monitoring.py
selfdrive/test/__init__.py
-selfdrive/test/longitudinal_maneuvers/*.py
+selfdrive/test/helpers.py
+selfdrive/test/setup_device_ci.sh
selfdrive/test/test_openpilot.py
selfdrive/test/test_fingerprints.py
-selfdrive/test/test_car_models.py
-selfdrive/test/openpilotci_upload.py
-
-selfdrive/test/process_replay/.gitignore
-selfdrive/test/process_replay/__init__.py
-selfdrive/test/process_replay/compare_logs.py
-selfdrive/test/process_replay/process_replay.py
-selfdrive/test/process_replay/test_processes.py
-selfdrive/test/process_replay/update_refs.py
-selfdrive/test/process_replay/ref_commit
-selfdrive/test/process_replay/README.md
+selfdrive/test/test_cpu_usage.py
selfdrive/ui/SConscript
-selfdrive/ui/*.c
selfdrive/ui/*.cc
-selfdrive/ui/*.h
selfdrive/ui/*.hpp
selfdrive/ui/ui
selfdrive/ui/spinner/Makefile
@@ -337,6 +337,9 @@ selfdrive/ui/text/Makefile
selfdrive/ui/text/text
selfdrive/ui/text/text.c
+selfdrive/ui/qt/*.cc
+selfdrive/ui/qt/*.hpp
+
selfdrive/camerad/SConscript
selfdrive/camerad/main.cc
selfdrive/camerad/bufs.h
@@ -380,11 +383,17 @@ selfdrive/modeld/transforms/loadyuv.cl
selfdrive/modeld/transforms/transform.[c,h]
selfdrive/modeld/transforms/transform.cl
+selfdrive/modeld/thneed/thneed.*
+selfdrive/modeld/thneed/include/*
+
selfdrive/modeld/runners/snpemodel.cc
selfdrive/modeld/runners/snpemodel.h
selfdrive/modeld/runners/runmodel.h
selfdrive/modeld/runners/run.h
+selfdrive/monitoring/dmonitoringd.py
+selfdrive/monitoring/driver_monitor.py
+
selfdrive/assets
selfdrive/assets/fonts/*.ttf
@@ -396,9 +405,7 @@ phonelibs/nanovg/*.h
phonelibs/libgralloc/**
phonelibs/linux/**
phonelibs/opencl/**
-phonelibs/curl/*
phonelibs/zlib/*
-phonelibs/boringssl/*
phonelibs/bzip2/*
phonelibs/openmax/**
@@ -420,9 +427,132 @@ phonelibs/android_system_core/**
installer/updater/updater
installer/updater/updater.cc
installer/updater/update.json
+installer/updater/update_kernel.json
installer/updater/Makefile
scripts/update_now.sh
scripts/stop_updater.sh
+pyextra/.gitignore
+
rednose/**
+
+cereal/.gitignore
+cereal/__init__.py
+cereal/car.capnp
+cereal/log.capnp
+cereal/services.py
+cereal/service_list.yaml
+cereal/SConscript
+cereal/include/**
+cereal/messaging/.gitignore
+cereal/messaging/__init__.py
+cereal/messaging/bridge.cc
+cereal/messaging/impl_msgq.cc
+cereal/messaging/impl_msgq.hpp
+cereal/messaging/impl_zmq.cc
+cereal/messaging/impl_zmq.hpp
+cereal/messaging/messaging.cc
+cereal/messaging/messaging.hpp
+cereal/messaging/messaging.pxd
+cereal/messaging/messaging_pyx.pyx
+cereal/messaging/messaging_pyx_setup.py
+cereal/messaging/msgq.cc
+cereal/messaging/msgq.hpp
+cereal/messaging/socketmaster.cc
+
+panda/.gitignore
+panda/__init__.py
+panda/VERSION
+panda/board/**
+panda/certs/**
+panda/common/**
+panda/crypto/**
+panda/python/**
+
+opendbc/.gitignore
+opendbc/__init__.py
+opendbc/can/__init__.py
+opendbc/can/SConscript
+opendbc/can/can_define.py
+opendbc/can/common.cc
+opendbc/can/common.h
+opendbc/can/common.pxd
+opendbc/can/common_dbc.h
+opendbc/can/common_pyx_setup.py
+opendbc/can/dbc.cc
+opendbc/can/dbc.py
+opendbc/can/dbc_template.cc
+opendbc/can/packer.cc
+opendbc/can/packer.py
+opendbc/can/packer_pyx.pyx
+opendbc/can/parser.cc
+opendbc/can/parser.py
+opendbc/can/parser_pyx.pyx
+opendbc/can/process_dbc.py
+opendbc/can/dbc_out/.gitkeep
+opendbc/can/dbc_out/.gitignore
+
+opendbc/chrysler_pacifica_2017_hybrid.dbc
+opendbc/chrysler_pacifica_2017_hybrid_private_fusion.dbc
+
+opendbc/gm_global_a_powertrain.dbc
+opendbc/gm_global_a_object.dbc
+opendbc/gm_global_a_chassis.dbc
+
+opendbc/ford_fusion_2018_pt.dbc
+opendbc/ford_fusion_2018_adas.dbc
+
+opendbc/honda_accord_s2t_2018_can_generated.dbc
+opendbc/honda_accord_lx15t_2018_can_generated.dbc
+opendbc/acura_ilx_2016_can_generated.dbc
+opendbc/acura_rdx_2018_can_generated.dbc
+opendbc/honda_civic_touring_2016_can_generated.dbc
+opendbc/honda_civic_hatchback_ex_2017_can_generated.dbc
+opendbc/honda_civic_sedan_16_diesel_2019_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_crv_hybrid_2019_can_generated.dbc
+opendbc/honda_fit_ex_2018_can_generated.dbc
+opendbc/honda_hrv_touring_2019_can_generated.dbc
+opendbc/honda_odyssey_exl_2018_generated.dbc
+opendbc/honda_odyssey_extreme_edition_2018_china_can_generated.dbc
+opendbc/honda_pilot_touring_2017_can_generated.dbc
+opendbc/honda_ridgeline_black_edition_2017_can_generated.dbc
+opendbc/honda_insight_ex_2019_can_generated.dbc
+opendbc/acura_ilx_2016_nidec.dbc
+
+opendbc/hyundai_kia_generic.dbc
+
+opendbc/mazda_2017.dbc
+
+opendbc/nissan_x_trail_2017.dbc
+opendbc/nissan_leaf_2018.dbc
+
+opendbc/subaru_global_2017_generated.dbc
+opendbc/subaru_outback_2015_generated.dbc
+opendbc/subaru_outback_2019_generated.dbc
+opendbc/subaru_forester_2017_generated.dbc
+
+opendbc/toyota_rav4_hybrid_2017_pt_generated.dbc
+opendbc/toyota_rav4_2017_pt_generated.dbc
+opendbc/toyota_prius_2017_pt_generated.dbc
+opendbc/toyota_corolla_2017_pt_generated.dbc
+opendbc/lexus_rx_350_2016_pt_generated.dbc
+opendbc/lexus_rx_hybrid_2017_pt_generated.dbc
+opendbc/toyota_nodsu_pt_generated.dbc
+opendbc/toyota_nodsu_hybrid_pt_generated.dbc
+opendbc/toyota_camry_hybrid_2018_pt_generated.dbc
+opendbc/toyota_highlander_2017_pt_generated.dbc
+opendbc/toyota_highlander_hybrid_2018_pt_generated.dbc
+opendbc/toyota_avalon_2017_pt_generated.dbc
+opendbc/toyota_sienna_xle_2018_pt_generated.dbc
+opendbc/lexus_is_2018_pt_generated.dbc
+opendbc/lexus_ct200h_2018_pt_generated.dbc
+opendbc/lexus_nx300h_2018_pt_generated.dbc
+opendbc/toyota_adas.dbc
+opendbc/toyota_tss2_adas.dbc
+
+opendbc/vw_mqb_2010.dbc
diff --git a/release/remote_build.py b/release/remote_build.py
deleted file mode 100755
index f80843cef9..0000000000
--- a/release/remote_build.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env python2
-import paramiko
-import os
-import sys
-import re
-import time
-import socket
-
-
-def start_build(name):
- ssh = paramiko.SSHClient()
- ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-
- key_file = open(os.path.join(os.path.dirname(__file__), "id_rsa_public"))
- key = paramiko.RSAKey.from_private_key(key_file)
-
- print("SSH to phone {}".format(name))
-
- # Try connecting for one minute
- t_start = time.time()
- while True:
- try:
- ssh.connect(hostname=name, port=8022, pkey=key, timeout=10)
- except (paramiko.ssh_exception.SSHException, socket.timeout, paramiko.ssh_exception.NoValidConnectionsError):
- print("Connection failed")
- if time.time() - t_start > 60:
- raise
- else:
- break
- time.sleep(1)
-
- conn = ssh.invoke_shell()
- branch = os.environ['GIT_BRANCH']
- commit = os.environ.get('GIT_COMMIT', branch)
-
- conn.send('uname -a\n')
-
- conn.send('cd /data/openpilot_source\n')
- conn.send("git reset --hard\n")
- conn.send("git fetch origin\n")
- conn.send("git checkout %s\n" % commit)
- conn.send("git clean -xdf\n")
- conn.send("git submodule update --init\n")
- conn.send("git submodule foreach --recursive git reset --hard\n")
- conn.send("git submodule foreach --recursive git clean -xdf\n")
- conn.send("echo \"git took $SECONDS seconds\"\n")
-
- push = "PUSH=master-ci" if branch == "master" else ""
-
- conn.send("%s /data/openpilot_source/release/build_devel.sh\n" % push)
- conn.send('echo "RESULT:" $?\n')
- conn.send("exit\n")
- return conn
-
-
-if __name__ == "__main__":
- eon_name = os.environ.get('eon_name', None)
-
- conn = start_build(eon_name)
-
- dat = b""
-
- while True:
- recvd = conn.recv(4096)
- if len(recvd) == 0:
- break
-
- dat += recvd
- sys.stdout.buffer.write(recvd)
- sys.stdout.flush()
-
- returns = re.findall(rb'^RESULT: (\d+)', dat[-1024:], flags=re.MULTILINE)
- sys.exit(int(returns[0]))
diff --git a/run_docker_tests.sh b/run_docker_tests.sh
deleted file mode 100755
index 1247c24de1..0000000000
--- a/run_docker_tests.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-set -e
-
-SETUP="cd /tmp/openpilot && "
-RUN="docker run --shm-size 1G --rm tmppilot /bin/sh -c"
-
-docker build -t tmppilot -f Dockerfile.openpilot .
-
-$RUN "$SETUP cd /tmp/openpilot/selfdrive/test/ && ./test_fingerprints.py"
-$RUN "$SETUP ./flake8_openpilot.sh"
-$RUN "$SETUP ./pylint_openpilot.sh"
-$RUN "$SETUP python -m unittest discover common"
-$RUN "$SETUP python -m unittest discover opendbc/can"
-$RUN "$SETUP python -m unittest discover selfdrive/boardd"
-$RUN "$SETUP python -m unittest discover selfdrive/controls"
-$RUN "$SETUP python -m unittest discover selfdrive/loggerd"
-$RUN "$SETUP python -m unittest discover selfdrive/car"
-$RUN "$SETUP python -m unittest discover selfdrive/locationd"
-$RUN "$SETUP python -m unittest discover selfdrive/athena"
-$RUN "$SETUP cd /tmp/openpilot/selfdrive/test/longitudinal_maneuvers && OPTEST=1 ./test_longitudinal.py"
-$RUN "$SETUP cd /tmp/openpilot/selfdrive/test/process_replay/ && ./test_processes.py"
-$RUN "$SETUP mkdir -p /data/params && cd /tmp/openpilot/selfdrive/test/ && ./test_car_models.py"
diff --git a/scripts/code_stats.py b/scripts/code_stats.py
index ccd32c7e50..d3bc48bcec 100755
--- a/scripts/code_stats.py
+++ b/scripts/code_stats.py
@@ -20,6 +20,7 @@ class Analyzer(ast.NodeVisitor):
for alias in node.names:
imps.add(alias.name)
self.generic_visit(node)
+
def visit_ImportFrom(self, node):
imps.add(node.module)
self.generic_visit(node)
@@ -38,4 +39,3 @@ for f in sorted(pyf):
print("%d lines of parsed openpilot python" % tlns)
#print(sorted(list(imps)))
-
diff --git a/scripts/waste.py b/scripts/waste.py
index 55aeba066a..48600253d3 100755
--- a/scripts/waste.py
+++ b/scripts/waste.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
from multiprocessing import Process
-from setproctitle import setproctitle
+from setproctitle import setproctitle # pylint: disable=no-name-in-module
import os
import numpy as np
from common.realtime import sec_since_boot
@@ -9,8 +9,8 @@ def waste(pid):
# set affinity
os.system("taskset -p %d %d" % (1 << pid, os.getpid()))
- m1 = np.zeros((200,200)) + 0.8
- m2 = np.zeros((200,200)) + 1.2
+ m1 = np.zeros((200, 200)) + 0.8
+ m2 = np.zeros((200, 200)) + 1.2
i = 1
st = sec_since_boot()
@@ -32,4 +32,3 @@ def main(gctx=None):
if __name__ == "__main__":
main()
-
diff --git a/selfdrive/assets/offroad/circled-checkmark.png b/selfdrive/assets/offroad/circled-checkmark.png
new file mode 100644
index 0000000000..bc6b49585d
Binary files /dev/null and b/selfdrive/assets/offroad/circled-checkmark.png differ
diff --git a/selfdrive/assets/offroad/icon_app_store.png b/selfdrive/assets/offroad/icon_app_store.png
new file mode 100644
index 0000000000..ae0dd95cee
Binary files /dev/null and b/selfdrive/assets/offroad/icon_app_store.png differ
diff --git a/selfdrive/assets/offroad/icon_calibration.png b/selfdrive/assets/offroad/icon_calibration.png
new file mode 100644
index 0000000000..c4ee0d63d4
Binary files /dev/null and b/selfdrive/assets/offroad/icon_calibration.png differ
diff --git a/selfdrive/assets/offroad/icon_checkmark.png b/selfdrive/assets/offroad/icon_checkmark.png
new file mode 100644
index 0000000000..06efdfb0cb
Binary files /dev/null and b/selfdrive/assets/offroad/icon_checkmark.png differ
diff --git a/selfdrive/assets/offroad/icon_chevron_right.png b/selfdrive/assets/offroad/icon_chevron_right.png
new file mode 100644
index 0000000000..a3aaa76486
Binary files /dev/null and b/selfdrive/assets/offroad/icon_chevron_right.png differ
diff --git a/selfdrive/assets/offroad/icon_connect_app.png b/selfdrive/assets/offroad/icon_connect_app.png
new file mode 100644
index 0000000000..cd216d3e6f
Binary files /dev/null and b/selfdrive/assets/offroad/icon_connect_app.png differ
diff --git a/selfdrive/assets/offroad/icon_eon.png b/selfdrive/assets/offroad/icon_eon.png
new file mode 100644
index 0000000000..72856c4e68
Binary files /dev/null and b/selfdrive/assets/offroad/icon_eon.png differ
diff --git a/selfdrive/assets/offroad/icon_map.png b/selfdrive/assets/offroad/icon_map.png
new file mode 100644
index 0000000000..21dd0bacc6
Binary files /dev/null and b/selfdrive/assets/offroad/icon_map.png differ
diff --git a/selfdrive/assets/offroad/icon_map_speed.png b/selfdrive/assets/offroad/icon_map_speed.png
new file mode 100644
index 0000000000..1eeab84600
Binary files /dev/null and b/selfdrive/assets/offroad/icon_map_speed.png differ
diff --git a/selfdrive/assets/offroad/icon_menu.png b/selfdrive/assets/offroad/icon_menu.png
new file mode 100644
index 0000000000..837cf5831c
Binary files /dev/null and b/selfdrive/assets/offroad/icon_menu.png differ
diff --git a/selfdrive/assets/offroad/icon_metric.png b/selfdrive/assets/offroad/icon_metric.png
new file mode 100644
index 0000000000..eaa2438fa3
Binary files /dev/null and b/selfdrive/assets/offroad/icon_metric.png differ
diff --git a/selfdrive/assets/offroad/icon_minus.png b/selfdrive/assets/offroad/icon_minus.png
new file mode 100644
index 0000000000..e5327c0d3b
Binary files /dev/null and b/selfdrive/assets/offroad/icon_minus.png differ
diff --git a/selfdrive/assets/offroad/icon_monitoring.png b/selfdrive/assets/offroad/icon_monitoring.png
new file mode 100644
index 0000000000..05f78811e2
Binary files /dev/null and b/selfdrive/assets/offroad/icon_monitoring.png differ
diff --git a/selfdrive/assets/offroad/icon_network.png b/selfdrive/assets/offroad/icon_network.png
new file mode 100644
index 0000000000..3236924f4d
Binary files /dev/null and b/selfdrive/assets/offroad/icon_network.png differ
diff --git a/selfdrive/assets/offroad/icon_openpilot.png b/selfdrive/assets/offroad/icon_openpilot.png
new file mode 100644
index 0000000000..0a90a87910
Binary files /dev/null and b/selfdrive/assets/offroad/icon_openpilot.png differ
diff --git a/selfdrive/assets/offroad/icon_openpilot_mirrored.png b/selfdrive/assets/offroad/icon_openpilot_mirrored.png
new file mode 100644
index 0000000000..23a7d5a552
Binary files /dev/null and b/selfdrive/assets/offroad/icon_openpilot_mirrored.png differ
diff --git a/selfdrive/assets/offroad/icon_play_store.png b/selfdrive/assets/offroad/icon_play_store.png
new file mode 100644
index 0000000000..1eca9d5890
Binary files /dev/null and b/selfdrive/assets/offroad/icon_play_store.png differ
diff --git a/selfdrive/assets/offroad/icon_plus.png b/selfdrive/assets/offroad/icon_plus.png
new file mode 100644
index 0000000000..92b448b0bd
Binary files /dev/null and b/selfdrive/assets/offroad/icon_plus.png differ
diff --git a/selfdrive/assets/offroad/icon_road.png b/selfdrive/assets/offroad/icon_road.png
new file mode 100644
index 0000000000..5868ed1ccc
Binary files /dev/null and b/selfdrive/assets/offroad/icon_road.png differ
diff --git a/selfdrive/assets/offroad/icon_settings.png b/selfdrive/assets/offroad/icon_settings.png
new file mode 100644
index 0000000000..d0c90a620d
Binary files /dev/null and b/selfdrive/assets/offroad/icon_settings.png differ
diff --git a/selfdrive/assets/offroad/icon_shell.png b/selfdrive/assets/offroad/icon_shell.png
new file mode 100644
index 0000000000..f1d655416a
Binary files /dev/null and b/selfdrive/assets/offroad/icon_shell.png differ
diff --git a/selfdrive/assets/offroad/icon_speed_limit.png b/selfdrive/assets/offroad/icon_speed_limit.png
new file mode 100644
index 0000000000..0aa7038f90
Binary files /dev/null and b/selfdrive/assets/offroad/icon_speed_limit.png differ
diff --git a/selfdrive/assets/offroad/icon_user.png b/selfdrive/assets/offroad/icon_user.png
new file mode 100644
index 0000000000..9b653cc4b3
Binary files /dev/null and b/selfdrive/assets/offroad/icon_user.png differ
diff --git a/selfdrive/assets/offroad/icon_warning.png b/selfdrive/assets/offroad/icon_warning.png
new file mode 100644
index 0000000000..50fe821127
Binary files /dev/null and b/selfdrive/assets/offroad/icon_warning.png differ
diff --git a/selfdrive/assets/offroad/illustration_arrow.png b/selfdrive/assets/offroad/illustration_arrow.png
new file mode 100644
index 0000000000..2219086641
Binary files /dev/null and b/selfdrive/assets/offroad/illustration_arrow.png differ
diff --git a/selfdrive/assets/offroad/illustration_sim_absent.png b/selfdrive/assets/offroad/illustration_sim_absent.png
new file mode 100644
index 0000000000..554097409b
Binary files /dev/null and b/selfdrive/assets/offroad/illustration_sim_absent.png differ
diff --git a/selfdrive/assets/offroad/illustration_sim_present.png b/selfdrive/assets/offroad/illustration_sim_present.png
new file mode 100644
index 0000000000..0856795f01
Binary files /dev/null and b/selfdrive/assets/offroad/illustration_sim_present.png differ
diff --git a/selfdrive/assets/offroad/illustration_training_lane_01.png b/selfdrive/assets/offroad/illustration_training_lane_01.png
new file mode 100644
index 0000000000..27d9bcee3e
Binary files /dev/null and b/selfdrive/assets/offroad/illustration_training_lane_01.png differ
diff --git a/selfdrive/assets/offroad/illustration_training_lane_02.png b/selfdrive/assets/offroad/illustration_training_lane_02.png
new file mode 100644
index 0000000000..4f3e2ef44c
Binary files /dev/null and b/selfdrive/assets/offroad/illustration_training_lane_02.png differ
diff --git a/selfdrive/assets/offroad/illustration_training_lead_01.png b/selfdrive/assets/offroad/illustration_training_lead_01.png
new file mode 100644
index 0000000000..12f3f6bae8
Binary files /dev/null and b/selfdrive/assets/offroad/illustration_training_lead_01.png differ
diff --git a/selfdrive/assets/offroad/illustration_training_lead_02.png b/selfdrive/assets/offroad/illustration_training_lead_02.png
new file mode 100644
index 0000000000..26c9ffe719
Binary files /dev/null and b/selfdrive/assets/offroad/illustration_training_lead_02.png differ
diff --git a/selfdrive/assets/offroad/indicator_wifi_0.png b/selfdrive/assets/offroad/indicator_wifi_0.png
new file mode 100644
index 0000000000..9cf9762ad3
Binary files /dev/null and b/selfdrive/assets/offroad/indicator_wifi_0.png differ
diff --git a/selfdrive/assets/offroad/indicator_wifi_100.png b/selfdrive/assets/offroad/indicator_wifi_100.png
new file mode 100644
index 0000000000..dc9f28fab3
Binary files /dev/null and b/selfdrive/assets/offroad/indicator_wifi_100.png differ
diff --git a/selfdrive/assets/offroad/indicator_wifi_25.png b/selfdrive/assets/offroad/indicator_wifi_25.png
new file mode 100644
index 0000000000..cbf9bc89e5
Binary files /dev/null and b/selfdrive/assets/offroad/indicator_wifi_25.png differ
diff --git a/selfdrive/assets/offroad/indicator_wifi_50.png b/selfdrive/assets/offroad/indicator_wifi_50.png
new file mode 100644
index 0000000000..8ee118a419
Binary files /dev/null and b/selfdrive/assets/offroad/indicator_wifi_50.png differ
diff --git a/selfdrive/assets/offroad/indicator_wifi_75.png b/selfdrive/assets/offroad/indicator_wifi_75.png
new file mode 100644
index 0000000000..bcbebce85d
Binary files /dev/null and b/selfdrive/assets/offroad/indicator_wifi_75.png differ
diff --git a/selfdrive/athena/athenad.py b/selfdrive/athena/athenad.py
index b9e8d79e6f..72e81a58bb 100755
--- a/selfdrive/athena/athenad.py
+++ b/selfdrive/athena/athenad.py
@@ -1,42 +1,45 @@
#!/usr/bin/env python3
-import json
-import os
+import base64
import hashlib
import io
+import json
+import os
+import queue
import random
import select
import socket
-import time
import threading
-import base64
-import requests
-import queue
+import time
from collections import namedtuple
from functools import partial
+from typing import Any
+
+import requests
from jsonrpc import JSONRPCResponseManager, dispatcher
-from websocket import create_connection, WebSocketTimeoutException, ABNF
-from selfdrive.loggerd.config import ROOT
+from websocket import ABNF, WebSocketTimeoutException, create_connection
import cereal.messaging as messaging
+from cereal.services import service_list
from common import android
-from common.basedir import PERSIST
from common.api import Api
+from common.basedir import PERSIST
from common.params import Params
from common.realtime import sec_since_boot
-from cereal.services import service_list
+from selfdrive.loggerd.config import ROOT
from selfdrive.swaglog import cloudlog
ATHENA_HOST = os.getenv('ATHENA_HOST', 'wss://athena.comma.ai')
-HANDLER_THREADS = os.getenv('HANDLER_THREADS', 4)
+HANDLER_THREADS = int(os.getenv('HANDLER_THREADS', "4"))
LOCAL_PORT_WHITELIST = set([8022])
dispatcher["echo"] = lambda s: s
-payload_queue = queue.Queue()
-response_queue = queue.Queue()
-upload_queue = queue.Queue()
-cancelled_uploads = set()
+payload_queue: Any = queue.Queue()
+response_queue: Any = queue.Queue()
+upload_queue: Any = queue.Queue()
+cancelled_uploads: Any = set()
UploadItem = namedtuple('UploadItem', ['path', 'url', 'headers', 'created_at', 'id'])
+
def handle_long_poll(ws):
end_event = threading.Event()
@@ -58,9 +61,10 @@ def handle_long_poll(ws):
end_event.set()
raise
finally:
- for i, thread in enumerate(threads):
+ for thread in threads:
thread.join()
+
def jsonrpc_handler(end_event):
dispatcher["startLocalProxy"] = partial(startLocalProxy, end_event)
while not end_event.is_set():
@@ -74,6 +78,7 @@ def jsonrpc_handler(end_event):
cloudlog.exception("athena jsonrpc handler failed")
response_queue.put_nowait(json.dumps({"error": str(e)}))
+
def upload_handler(end_event):
while not end_event.is_set():
try:
@@ -87,6 +92,7 @@ def upload_handler(end_event):
except Exception:
cloudlog.exception("athena.upload_handler.exception")
+
def _do_upload(upload_item):
with open(upload_item.path, "rb") as f:
size = os.fstat(f.fileno()).st_size
@@ -95,6 +101,7 @@ def _do_upload(upload_item):
headers={**upload_item.headers, 'Content-Length': str(size)},
timeout=10)
+
# security: user should be able to request any message from their car
@dispatcher.add_method
def getMessage(service=None, timeout=1000):
@@ -109,11 +116,13 @@ def getMessage(service=None, timeout=1000):
return ret.to_dict()
+
@dispatcher.add_method
def listDataDirectory():
files = [os.path.relpath(os.path.join(dp, f), ROOT) for dp, dn, fn in os.walk(ROOT) for f in fn]
return files
+
@dispatcher.add_method
def reboot():
thermal_sock = messaging.sub_sock("thermal", timeout=1000)
@@ -129,6 +138,7 @@ def reboot():
return {"success": 1}
+
@dispatcher.add_method
def uploadFileToUrl(fn, url, headers):
if len(fn) == 0 or fn[0] == '/' or '..' in fn:
@@ -137,7 +147,7 @@ def uploadFileToUrl(fn, url, headers):
if not os.path.exists(path):
return 404
- item = UploadItem(path=path, url=url, headers=headers, created_at=int(time.time()*1000), id=None)
+ item = UploadItem(path=path, url=url, headers=headers, created_at=int(time.time() * 1000), id=None)
upload_id = hashlib.sha1(str(item).encode()).hexdigest()
item = item._replace(id=upload_id)
@@ -145,10 +155,12 @@ def uploadFileToUrl(fn, url, headers):
return {"enqueued": 1, "item": item._asdict()}
+
@dispatcher.add_method
def listUploadQueue():
return [item._asdict() for item in list(upload_queue.queue)]
+
@dispatcher.add_method
def cancelUpload(upload_id):
upload_ids = set(item.id for item in list(upload_queue.queue))
@@ -158,6 +170,7 @@ def cancelUpload(upload_id):
cancelled_uploads.add(upload_id)
return {"success": 1}
+
def startLocalProxy(global_end_event, remote_ws_uri, local_port):
try:
if local_port not in LOCAL_PORT_WHITELIST:
@@ -188,18 +201,21 @@ def startLocalProxy(global_end_event, remote_ws_uri, local_port):
cloudlog.exception("athenad.startLocalProxy.exception")
raise e
+
@dispatcher.add_method
def getPublicKey():
- if not os.path.isfile(PERSIST+'/comma/id_rsa.pub'):
+ if not os.path.isfile(PERSIST + '/comma/id_rsa.pub'):
return None
- with open(PERSIST+'/comma/id_rsa.pub', 'r') as f:
+ with open(PERSIST + '/comma/id_rsa.pub', 'r') as f:
return f.read()
+
@dispatcher.add_method
def getSshAuthorizedKeys():
return Params().get("GithubSshKeys", encoding='utf8') or ''
+
@dispatcher.add_method
def getSimInfo():
sim_state = android.getprop("gsm.sim.state").split(",")
@@ -218,6 +234,7 @@ def getSimInfo():
'data_connected': cell_data_connected
}
+
@dispatcher.add_method
def takeSnapshot():
from selfdrive.camerad.snapshot.snapshot import snapshot, jpeg_write
@@ -235,6 +252,7 @@ def takeSnapshot():
else:
raise Exception("not available while camerad is started")
+
def ws_proxy_recv(ws, local_sock, ssock, end_event, global_end_event):
while not (end_event.is_set() or global_end_event.is_set()):
try:
@@ -250,6 +268,7 @@ def ws_proxy_recv(ws, local_sock, ssock, end_event, global_end_event):
local_sock.close()
end_event.set()
+
def ws_proxy_send(ws, local_sock, signal_sock, end_event):
while not end_event.is_set():
try:
@@ -270,6 +289,7 @@ def ws_proxy_send(ws, local_sock, signal_sock, end_event):
cloudlog.exception("athenad.ws_proxy_send.exception")
end_event.set()
+
def ws_recv(ws, end_event):
while not end_event.is_set():
try:
@@ -279,13 +299,14 @@ def ws_recv(ws, end_event):
data = data.decode("utf-8")
payload_queue.put_nowait(data)
elif opcode == ABNF.OPCODE_PING:
- Params().put("LastAthenaPingTime", str(int(sec_since_boot()*1e9)))
+ Params().put("LastAthenaPingTime", str(int(sec_since_boot() * 1e9)))
except WebSocketTimeoutException:
pass
except Exception:
cloudlog.exception("athenad.ws_recv.exception")
end_event.set()
+
def ws_send(ws, end_event):
while not end_event.is_set():
try:
@@ -297,9 +318,11 @@ def ws_send(ws, end_event):
cloudlog.exception("athenad.ws_send.exception")
end_event.set()
+
def backoff(retries):
return random.randrange(0, min(128, int(2 ** retries)))
+
def main():
params = Params()
dongle_id = params.get("DongleId").decode('utf-8')
@@ -326,5 +349,6 @@ def main():
time.sleep(backoff(conn_retries))
+
if __name__ == "__main__":
main()
diff --git a/selfdrive/athena/test_helpers.py b/selfdrive/athena/test_helpers.py
index 2335ce89c5..77a94c0787 100644
--- a/selfdrive/athena/test_helpers.py
+++ b/selfdrive/athena/test_helpers.py
@@ -8,6 +8,7 @@ import time
from functools import wraps
from multiprocessing import Process
+
class EchoSocket():
def __init__(self, port):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -15,7 +16,7 @@ class EchoSocket():
self.socket.listen(1)
def run(self):
- conn, client_address = self.socket.accept()
+ conn, _ = self.socket.accept()
conn.settimeout(5.0)
try:
@@ -32,6 +33,7 @@ class EchoSocket():
self.socket.shutdown(0)
self.socket.close()
+
class MockApi():
def __init__(self, dongle_id):
pass
@@ -39,11 +41,12 @@ class MockApi():
def get_token(self):
return "fake-token"
+
class MockParams():
def __init__(self):
self.params = {
"DongleId": b"0000000000000000",
- "GithubSshKeys": b"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC307aE+nuHzTAgaJhzSf5v7ZZQW9gaperjhCmyPyl4PzY7T1mDGenTlVTN7yoVFZ9UfO9oMQqo0n1OwDIiqbIFxqnhrHU0cYfj88rI85m5BEKlNu5RdaVTj1tcbaPpQc5kZEolaI1nDDjzV0lwS7jo5VYDHseiJHlik3HH1SgtdtsuamGR2T80q1SyW+5rHoMOJG73IH2553NnWuikKiuikGHUYBd00K1ilVAK2xSiMWJp55tQfZ0ecr9QjEsJ+J/efL4HqGNXhffxvypCXvbUYAFSddOwXUPo5BTKevpxMtH+2YrkpSjocWA04VnTYFiPG6U4ItKmbLOTFZtPzoez private"
+ "GithubSshKeys": b"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC307aE+nuHzTAgaJhzSf5v7ZZQW9gaperjhCmyPyl4PzY7T1mDGenTlVTN7yoVFZ9UfO9oMQqo0n1OwDIiqbIFxqnhrHU0cYfj88rI85m5BEKlNu5RdaVTj1tcbaPpQc5kZEolaI1nDDjzV0lwS7jo5VYDHseiJHlik3HH1SgtdtsuamGR2T80q1SyW+5rHoMOJG73IH2553NnWuikKiuikGHUYBd00K1ilVAK2xSiMWJp55tQfZ0ecr9QjEsJ+J/efL4HqGNXhffxvypCXvbUYAFSddOwXUPo5BTKevpxMtH+2YrkpSjocWA04VnTYFiPG6U4ItKmbLOTFZtPzoez private" # noqa: E501
}
def get(self, k, encoding=None):
@@ -52,6 +55,7 @@ class MockParams():
ret = ret.decode(encoding)
return ret
+
class MockWebsocket():
def __init__(self, recv_queue, send_queue):
self.recv_queue = recv_queue
@@ -66,6 +70,7 @@ class MockWebsocket():
def send(self, data, opcode):
self.send_queue.put_nowait((data, opcode))
+
class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def do_PUT(self):
length = int(self.headers['Content-Length'])
@@ -73,6 +78,7 @@ class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
self.send_response(201, "Created")
self.end_headers()
+
def http_server(port_queue, **kwargs):
while 1:
try:
@@ -83,6 +89,7 @@ def http_server(port_queue, **kwargs):
if e.errno == 98:
continue
+
def with_http_server(func):
@wraps(func)
def inner(*args, **kwargs):
diff --git a/selfdrive/boardd/SConscript b/selfdrive/boardd/SConscript
index 14c1ff780d..94e630a641 100644
--- a/selfdrive/boardd/SConscript
+++ b/selfdrive/boardd/SConscript
@@ -1,9 +1,8 @@
-Import('env', 'common', 'messaging')
+Import('env', 'common', 'cereal', 'messaging', 'cython_dependencies')
-env.Program('boardd.cc', LIBS=['usb-1.0', common, messaging, 'pthread', 'zmq', 'capnp', 'kj'])
+env.Program('boardd', ['boardd.cc', 'panda.cc', 'pigeon.cc'], LIBS=['usb-1.0', common, cereal, messaging, 'pthread', 'zmq', 'capnp', 'kj'])
env.Library('libcan_list_to_can_capnp', ['can_list_to_can_capnp.cc'])
-env.Command(['boardd_api_impl.so'],
- ['libcan_list_to_can_capnp.a', 'boardd_api_impl.pyx', 'boardd_setup.py'],
- "cd selfdrive/boardd && python3 boardd_setup.py build_ext --inplace")
-
+env.Command(['boardd_api_impl.so', 'boardd_api_impl.cpp'],
+ cython_dependencies + ['libcan_list_to_can_capnp.a', 'boardd_api_impl.pyx', 'boardd_setup.py'],
+ "cd selfdrive/boardd && python3 boardd_setup.py build_ext --inplace")
diff --git a/selfdrive/boardd/boardd.cc b/selfdrive/boardd/boardd.cc
index d5990bc1d8..146e219f90 100644
--- a/selfdrive/boardd/boardd.cc
+++ b/selfdrive/boardd/boardd.cc
@@ -1,656 +1,256 @@
#include
-#include
#include
#include
-#include
#include
#include
#include
+#include
#include
#include
-#include
#include
-#include
-#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
-#include
-#include "cereal/gen/cpp/log.capnp.h"
#include "cereal/gen/cpp/car.capnp.h"
#include "common/util.h"
-#include "common/messaging.h"
#include "common/params.h"
#include "common/swaglog.h"
#include "common/timing.h"
#include "messaging.hpp"
-#include
-#include
+#include "panda.h"
+#include "pigeon.h"
-// double the FIFO size
-#define RECV_SIZE (0x1000)
-#define TIMEOUT 0
#define MAX_IR_POWER 0.5f
#define MIN_IR_POWER 0.0f
-#define CUTOFF_GAIN 0.015625f // iso400
-#define SATURATE_GAIN 0.0625f // iso1600
+#define CUTOFF_IL 200
+#define SATURATE_IL 1600
#define NIBBLE_TO_HEX(n) ((n) < 10 ? (n) + '0' : ((n) - 10) + 'a')
-#define VOLTAGE_K 0.091 // LPF gain for 5s tau (dt/tau / (dt/tau + 1))
-
-namespace {
+Panda * panda = NULL;
+std::atomic safety_setter_thread_running(false);
volatile sig_atomic_t do_exit = 0;
-
-struct __attribute__((packed)) timestamp_t {
- uint16_t year;
- uint8_t month;
- uint8_t day;
- uint8_t weekday;
- uint8_t hour;
- uint8_t minute;
- uint8_t second;
-};
-
-libusb_context *ctx = NULL;
-libusb_device_handle *dev_handle = NULL;
-pthread_mutex_t usb_lock;
-
bool spoofing_started = false;
bool fake_send = false;
-bool loopback_can = false;
-cereal::HealthData::HwType hw_type = cereal::HealthData::HwType::UNKNOWN;
-bool is_pigeon = false;
-const uint32_t NO_IGNITION_CNT_MAX = 2 * 60 * 60 * 30; // turn off charge after 30 hrs
-const float VBATT_START_CHARGING = 11.5;
-const float VBATT_PAUSE_CHARGING = 11.0;
-float voltage_f = 12.5; // filtered voltage
-uint32_t no_ignition_cnt = 0;
bool connected_once = false;
-bool ignition_last = false;
-bool safety_setter_thread_initialized = false;
-pthread_t safety_setter_thread_handle;
+struct tm get_time(){
+ time_t rawtime;
+ time(&rawtime);
-bool pigeon_thread_initialized = false;
-pthread_t pigeon_thread_handle;
+ struct tm sys_time;
+ gmtime_r(&rawtime, &sys_time);
-bool pigeon_needs_init;
+ return sys_time;
+}
-void pigeon_init();
-void *pigeon_thread(void *crap);
+bool time_valid(struct tm sys_time){
+ return 1900 + sys_time.tm_year >= 2019;
+}
-void *safety_setter_thread(void *s) {
+void safety_setter_thread() {
+ LOGD("Starting safety setter thread");
// diagnostic only is the default, needed for VIN query
- pthread_mutex_lock(&usb_lock);
- libusb_control_transfer(dev_handle, 0x40, 0xdc, (uint16_t)(cereal::CarParams::SafetyModel::ELM327), 0, NULL, 0, TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
-
- char *value_vin;
- size_t value_vin_sz = 0;
+ panda->set_safety_model(cereal::CarParams::SafetyModel::ELM327);
// switch to SILENT when CarVin param is read
while (1) {
- if (do_exit) return NULL;
- const int result = read_db_value("CarVin", &value_vin, &value_vin_sz);
- if (value_vin_sz > 0) {
+ if (do_exit || !panda->connected){
+ safety_setter_thread_running = false;
+ return;
+ };
+
+ std::vector value_vin = read_db_bytes("CarVin");
+ if (value_vin.size() > 0) {
// sanity check VIN format
- assert(value_vin_sz == 17);
+ assert(value_vin.size() == 17);
+ std::string str_vin(value_vin.begin(), value_vin.end());
+ LOGW("got CarVin %s", str_vin.c_str());
break;
}
usleep(100*1000);
}
- LOGW("got CarVin %s", value_vin);
- free(value_vin);
// VIN query done, stop listening to OBDII
- pthread_mutex_lock(&usb_lock);
- libusb_control_transfer(dev_handle, 0x40, 0xdc, (uint16_t)(cereal::CarParams::SafetyModel::NO_OUTPUT), 0, NULL, 0, TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
-
- char *value;
- size_t value_sz = 0;
+ panda->set_safety_model(cereal::CarParams::SafetyModel::NO_OUTPUT);
+ std::vector params;
LOGW("waiting for params to set safety model");
while (1) {
- if (do_exit) return NULL;
+ if (do_exit || !panda->connected){
+ safety_setter_thread_running = false;
+ return;
+ };
- const int result = read_db_value("CarParams", &value, &value_sz);
- if (value_sz > 0) break;
+ params = read_db_bytes("CarParams");
+ if (params.size() > 0) break;
usleep(100*1000);
}
- LOGW("got %d bytes CarParams", value_sz);
+ LOGW("got %d bytes CarParams", params.size());
// format for board, make copy due to alignment issues, will be freed on out of scope
- auto amsg = kj::heapArray((value_sz / sizeof(capnp::word)) + 1);
- memcpy(amsg.begin(), value, value_sz);
- free(value);
+ auto amsg = kj::heapArray((params.size() / sizeof(capnp::word)) + 1);
+ memcpy(amsg.begin(), params.data(), params.size());
capnp::FlatArrayMessageReader cmsg(amsg);
cereal::CarParams::Reader car_params = cmsg.getRoot();
+ cereal::CarParams::SafetyModel safety_model = car_params.getSafetyModel();
- int safety_model = int(car_params.getSafetyModel());
auto safety_param = car_params.getSafetyParam();
- LOGW("setting safety model: %d with param %d", safety_model, safety_param);
-
- pthread_mutex_lock(&usb_lock);
+ LOGW("setting safety model: %d with param %d", (int)safety_model, safety_param);
- // set in the mutex to avoid race
- safety_setter_thread_initialized = false;
+ panda->set_safety_model(safety_model, safety_param);
- libusb_control_transfer(dev_handle, 0x40, 0xdc, safety_model, safety_param, NULL, 0, TIMEOUT);
-
- pthread_mutex_unlock(&usb_lock);
-
- return NULL;
+ safety_setter_thread_running = false;
}
-// must be called before threads or with mutex
+
bool usb_connect() {
- int err, err2;
- unsigned char hw_query[1] = {0};
- unsigned char fw_sig_buf[128];
- unsigned char fw_sig_hex_buf[16];
- unsigned char serial_buf[16];
- const char *serial;
- int serial_sz = 0;
-
- ignition_last = false;
-
- if (dev_handle != NULL){
- libusb_close(dev_handle);
- dev_handle = NULL;
+ try {
+ assert(panda == NULL);
+ panda = new Panda();
+ } catch (std::exception &e) {
+ return false;
}
- dev_handle = libusb_open_device_with_vid_pid(ctx, 0xbbaa, 0xddcc);
- if (dev_handle == NULL) { goto fail; }
-
- err = libusb_set_configuration(dev_handle, 1);
- if (err != 0) { goto fail; }
-
- err = libusb_claim_interface(dev_handle, 0);
- if (err != 0) { goto fail; }
-
- if (loopback_can) {
- libusb_control_transfer(dev_handle, 0xc0, 0xe5, 1, 0, NULL, 0, TIMEOUT);
+ if (getenv("BOARDD_LOOPBACK")) {
+ panda->set_loopback(true);
}
- // get panda fw
- err = libusb_control_transfer(dev_handle, 0xc0, 0xd3, 0, 0, fw_sig_buf, 64, TIMEOUT);
- err2 = libusb_control_transfer(dev_handle, 0xc0, 0xd4, 0, 0, fw_sig_buf + 64, 64, TIMEOUT);
- if ((err == 64) && (err2 == 64)) {
- printf("FW signature read\n");
- write_db_value("PandaFirmware", (const char *)fw_sig_buf, 128);
+ const char *fw_sig_buf = panda->get_firmware_version();
+ if (fw_sig_buf){
+ write_db_value("PandaFirmware", fw_sig_buf, 128);
+ // Convert to hex for offroad
+ char fw_sig_hex_buf[16] = {0};
for (size_t i = 0; i < 8; i++){
- fw_sig_hex_buf[2*i] = NIBBLE_TO_HEX(fw_sig_buf[i] >> 4);
- fw_sig_hex_buf[2*i+1] = NIBBLE_TO_HEX(fw_sig_buf[i] & 0xF);
+ fw_sig_hex_buf[2*i] = NIBBLE_TO_HEX((uint8_t)fw_sig_buf[i] >> 4);
+ fw_sig_hex_buf[2*i+1] = NIBBLE_TO_HEX((uint8_t)fw_sig_buf[i] & 0xF);
}
- write_db_value("PandaFirmwareHex", (const char *)fw_sig_hex_buf, 16);
- }
- else { goto fail; }
+
+ write_db_value("PandaFirmwareHex", fw_sig_hex_buf, 16);
+ LOGW("fw signature: %.*s", 16, fw_sig_hex_buf);
+
+ delete[] fw_sig_buf;
+ } else { return false; }
// get panda serial
- err = libusb_control_transfer(dev_handle, 0xc0, 0xd0, 0, 0, serial_buf, 16, TIMEOUT);
+ const char *serial_buf = panda->get_serial();
+ if (serial_buf) {
+ size_t serial_sz = strnlen(serial_buf, 16);
- if (err > 0) {
- serial = (const char *)serial_buf;
- serial_sz = strnlen(serial, err);
- write_db_value("PandaDongleId", serial, serial_sz);
- printf("panda serial: %.*s\n", serial_sz, serial);
- }
- else { goto fail; }
+ write_db_value("PandaDongleId", serial_buf, serial_sz);
+ LOGW("panda serial: %.*s", serial_sz, serial_buf);
+
+ delete[] serial_buf;
+ } else { return false; }
// power on charging, only the first time. Panda can also change mode and it causes a brief disconneciton
#ifndef __x86_64__
if (!connected_once) {
- libusb_control_transfer(dev_handle, 0xc0, 0xe6, (uint16_t)(cereal::HealthData::UsbPowerMode::CDP), 0, NULL, 0, TIMEOUT);
+ panda->set_usb_power_mode(cereal::HealthData::UsbPowerMode::CDP);
}
#endif
- connected_once = true;
- libusb_control_transfer(dev_handle, 0xc0, 0xc1, 0, 0, hw_query, 1, TIMEOUT);
-
- hw_type = (cereal::HealthData::HwType)(hw_query[0]);
- is_pigeon = (hw_type == cereal::HealthData::HwType::GREY_PANDA) ||
- (hw_type == cereal::HealthData::HwType::BLACK_PANDA) ||
- (hw_type == cereal::HealthData::HwType::UNO);
- if (is_pigeon) {
- LOGW("panda with gps detected");
- pigeon_needs_init = true;
- if (!pigeon_thread_initialized) {
- err = pthread_create(&pigeon_thread_handle, NULL, pigeon_thread, NULL);
- assert(err == 0);
- pigeon_thread_initialized = true;
- }
- }
-
- if (hw_type == cereal::HealthData::HwType::UNO){
- // Get time from system
- time_t rawtime;
- time(&rawtime);
-
- struct tm * sys_time = gmtime(&rawtime);
-
- // Get time from RTC
- timestamp_t rtc_time;
- libusb_control_transfer(dev_handle, 0xc0, 0xa0, 0, 0, (unsigned char*)&rtc_time, sizeof(rtc_time), TIMEOUT);
+ if (panda->has_rtc){
+ struct tm sys_time = get_time();
+ struct tm rtc_time = panda->get_rtc();
- //printf("System: %d-%d-%d\t%d:%d:%d\n", 1900 + sys_time->tm_year, 1 + sys_time->tm_mon, sys_time->tm_mday, sys_time->tm_hour, sys_time->tm_min, sys_time->tm_sec);
- //printf("RTC: %d-%d-%d\t%d:%d:%d\n", rtc_time.year, rtc_time.month, rtc_time.day, rtc_time.hour, rtc_time.minute, rtc_time.second);
-
- // Update system time from RTC if it looks off, and RTC time is good
- if (1900 + sys_time->tm_year < 2019 && rtc_time.year >= 2019){
+ if (!time_valid(sys_time) && time_valid(rtc_time)) {
LOGE("System time wrong, setting from RTC");
- struct tm new_time = { 0 };
- new_time.tm_year = rtc_time.year - 1900;
- new_time.tm_mon = rtc_time.month - 1;
- new_time.tm_mday = rtc_time.day;
- new_time.tm_hour = rtc_time.hour;
- new_time.tm_min = rtc_time.minute;
- new_time.tm_sec = rtc_time.second;
-
setenv("TZ","UTC",1);
- const struct timeval tv = {mktime(&new_time), 0};
+ const struct timeval tv = {mktime(&rtc_time), 0};
settimeofday(&tv, 0);
}
}
+ connected_once = true;
return true;
-fail:
- return false;
}
// must be called before threads or with mutex
void usb_retry_connect() {
- LOG("attempting to connect");
+ LOGW("attempting to connect");
while (!usb_connect()) { usleep(100*1000); }
LOGW("connected to board");
}
-void handle_usb_issue(int err, const char func[]) {
- LOGE_100("usb error %d \"%s\" in %s", err, libusb_strerror((enum libusb_error)err), func);
- if (err == -4) {
- LOGE("lost connection");
- usb_retry_connect();
- }
- // TODO: check other errors, is simply retrying okay?
-}
-
-void can_recv(PubSocket *publisher) {
- int err;
- uint32_t data[RECV_SIZE/4];
- int recv;
- uint32_t f1, f2;
-
+void can_recv(PubMaster &pm) {
uint64_t start_time = nanos_since_boot();
- // do recv
- pthread_mutex_lock(&usb_lock);
-
- do {
- err = libusb_bulk_transfer(dev_handle, 0x81, (uint8_t*)data, RECV_SIZE, &recv, TIMEOUT);
- if (err != 0) { handle_usb_issue(err, __func__); }
- if (err == -8) { LOGE_100("overflow got 0x%x", recv); };
-
- // timeout is okay to exit, recv still happened
- if (err == -7) { break; }
- } while(err != 0);
-
- pthread_mutex_unlock(&usb_lock);
-
- // return if length is 0
- if (recv <= 0) {
- return;
- } else if (recv == RECV_SIZE) {
- LOGW("Receive buffer full");
- }
-
// create message
capnp::MallocMessageBuilder msg;
cereal::Event::Builder event = msg.initRoot();
event.setLogMonoTime(start_time);
- size_t num_msg = recv / 0x10;
- auto canData = event.initCan(num_msg);
-
- // populate message
- for (int i = 0; i < num_msg; i++) {
- if (data[i*4] & 4) {
- // extended
- canData[i].setAddress(data[i*4] >> 3);
- //printf("got extended: %x\n", data[i*4] >> 3);
- } else {
- // normal
- canData[i].setAddress(data[i*4] >> 21);
- }
- canData[i].setBusTime(data[i*4+1] >> 16);
- int len = data[i*4+1]&0xF;
- canData[i].setDat(kj::arrayPtr((uint8_t*)&data[i*4+2], len));
- canData[i].setSrc((data[i*4+1] >> 4) & 0xff);
- }
-
- // send to can
- auto words = capnp::messageToFlatArray(msg);
- auto bytes = words.asBytes();
- publisher->send((char*)bytes.begin(), bytes.size());
-}
-
-void can_health(PubSocket *publisher) {
- int cnt;
- int err;
-
- // copied from panda/board/main.c
- struct __attribute__((packed)) health {
- uint32_t uptime;
- uint32_t voltage;
- uint32_t current;
- uint32_t can_rx_errs;
- uint32_t can_send_errs;
- uint32_t can_fwd_errs;
- uint32_t gmlan_send_errs;
- uint32_t faults;
- uint8_t ignition_line;
- uint8_t ignition_can;
- uint8_t controls_allowed;
- uint8_t gas_interceptor_detected;
- uint8_t car_harness_status;
- uint8_t usb_power_mode;
- uint8_t safety_model;
- uint8_t fault_status;
- uint8_t power_save_enabled;
- } health;
-
- // create message
- capnp::MallocMessageBuilder msg;
- cereal::Event::Builder event = msg.initRoot();
- event.setLogMonoTime(nanos_since_boot());
- auto healthData = event.initHealth();
-
- bool received = false;
-
- // recv from board
- if (dev_handle != NULL) {
- pthread_mutex_lock(&usb_lock);
- cnt = libusb_control_transfer(dev_handle, 0xc0, 0xd2, 0, 0, (unsigned char*)&health, sizeof(health), TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
-
- received = (cnt == sizeof(health));
- }
-
- // No panda connected, send empty health packet
- if (!received){
- healthData.setHwType(cereal::HealthData::HwType::UNKNOWN);
-
- auto words = capnp::messageToFlatArray(msg);
- auto bytes = words.asBytes();
- publisher->send((char*)bytes.begin(), bytes.size());
- return;
- }
-
- if (spoofing_started) {
- health.ignition_line = 1;
- }
-
- voltage_f = VOLTAGE_K * (health.voltage / 1000.0) + (1.0 - VOLTAGE_K) * voltage_f; // LPF
-
- // Make sure CAN buses are live: safety_setter_thread does not work if Panda CAN are silent and there is only one other CAN node
- if (health.safety_model == (uint8_t)(cereal::CarParams::SafetyModel::SILENT)) {
- pthread_mutex_lock(&usb_lock);
- libusb_control_transfer(dev_handle, 0x40, 0xdc, (uint16_t)(cereal::CarParams::SafetyModel::NO_OUTPUT), 0, NULL, 0, TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
- }
-
- bool ignition = ((health.ignition_line != 0) || (health.ignition_can != 0));
-
- if (ignition) {
- no_ignition_cnt = 0;
- } else {
- no_ignition_cnt += 1;
- }
-
-#ifndef __x86_64__
- bool cdp_mode = health.usb_power_mode == (uint8_t)(cereal::HealthData::UsbPowerMode::CDP);
- bool no_ignition_exp = no_ignition_cnt > NO_IGNITION_CNT_MAX;
- if ((no_ignition_exp || (voltage_f < VBATT_PAUSE_CHARGING)) && cdp_mode && !ignition) {
- char *disable_power_down = NULL;
- size_t disable_power_down_sz = 0;
- const int result = read_db_value("DisablePowerDown", &disable_power_down, &disable_power_down_sz);
- if (disable_power_down_sz != 1 || disable_power_down[0] != '1') {
- printf("TURN OFF CHARGING!\n");
- pthread_mutex_lock(&usb_lock);
- libusb_control_transfer(dev_handle, 0xc0, 0xe6, (uint16_t)(cereal::HealthData::UsbPowerMode::CLIENT), 0, NULL, 0, TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
- printf("POWER DOWN DEVICE\n");
- system("service call power 17 i32 0 i32 1");
- }
- if (disable_power_down) free(disable_power_down);
- }
- if (!no_ignition_exp && (voltage_f > VBATT_START_CHARGING) && !cdp_mode) {
- printf("TURN ON CHARGING!\n");
- pthread_mutex_lock(&usb_lock);
- libusb_control_transfer(dev_handle, 0xc0, 0xe6, (uint16_t)(cereal::HealthData::UsbPowerMode::CDP), 0, NULL, 0, TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
- }
- // set power save state enabled when car is off and viceversa when it's on
- if (ignition && (health.power_save_enabled == 1)) {
- pthread_mutex_lock(&usb_lock);
- libusb_control_transfer(dev_handle, 0xc0, 0xe7, 0, 0, NULL, 0, TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
- }
- if (!ignition && (health.power_save_enabled == 0)) {
- pthread_mutex_lock(&usb_lock);
- libusb_control_transfer(dev_handle, 0xc0, 0xe7, 1, 0, NULL, 0, TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
- }
- // set safety mode to NO_OUTPUT when car is off. ELM327 is an alternative if we want to leverage athenad/connect
- if (!ignition && (health.safety_model != (uint8_t)(cereal::CarParams::SafetyModel::NO_OUTPUT))) {
- pthread_mutex_lock(&usb_lock);
- libusb_control_transfer(dev_handle, 0x40, 0xdc, (uint16_t)(cereal::CarParams::SafetyModel::NO_OUTPUT), 0, NULL, 0, TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
- }
-#endif
-
- // clear VIN, CarParams, and set new safety on car start
- if (ignition && !ignition_last) {
- int result = delete_db_value("CarVin");
- assert((result == 0) || (result == ERR_NO_VALUE));
- result = delete_db_value("CarParams");
- assert((result == 0) || (result == ERR_NO_VALUE));
-
- if (!safety_setter_thread_initialized) {
- err = pthread_create(&safety_setter_thread_handle, NULL, safety_setter_thread, NULL);
- assert(err == 0);
- safety_setter_thread_initialized = true;
- }
- }
-
- // Get fan RPM
- uint16_t fan_speed_rpm = 0;
-
- pthread_mutex_lock(&usb_lock);
- int sz = libusb_control_transfer(dev_handle, 0xc0, 0xb2, 0, 0, (unsigned char*)&fan_speed_rpm, sizeof(fan_speed_rpm), TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
-
- // Write to rtc once per minute when no ignition present
- if ((hw_type == cereal::HealthData::HwType::UNO) && !ignition && (no_ignition_cnt % 120 == 1)){
- // Get time from system
- time_t rawtime;
- time(&rawtime);
-
- struct tm * sys_time = gmtime(&rawtime);
-
- // Write time to RTC if it looks reasonable
- if (1900 + sys_time->tm_year >= 2019){
- pthread_mutex_lock(&usb_lock);
- libusb_control_transfer(dev_handle, 0x40, 0xa1, (uint16_t)(1900 + sys_time->tm_year), 0, NULL, 0, TIMEOUT);
- libusb_control_transfer(dev_handle, 0x40, 0xa2, (uint16_t)(1 + sys_time->tm_mon), 0, NULL, 0, TIMEOUT);
- libusb_control_transfer(dev_handle, 0x40, 0xa3, (uint16_t)sys_time->tm_mday, 0, NULL, 0, TIMEOUT);
- // libusb_control_transfer(dev_handle, 0x40, 0xa4, (uint16_t)(1 + sys_time->tm_wday), 0, NULL, 0, TIMEOUT);
- libusb_control_transfer(dev_handle, 0x40, 0xa5, (uint16_t)sys_time->tm_hour, 0, NULL, 0, TIMEOUT);
- libusb_control_transfer(dev_handle, 0x40, 0xa6, (uint16_t)sys_time->tm_min, 0, NULL, 0, TIMEOUT);
- libusb_control_transfer(dev_handle, 0x40, 0xa7, (uint16_t)sys_time->tm_sec, 0, NULL, 0, TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
- }
- }
-
- ignition_last = ignition;
-
- // set fields
- healthData.setUptime(health.uptime);
- healthData.setVoltage(health.voltage);
- healthData.setCurrent(health.current);
- healthData.setIgnitionLine(health.ignition_line);
- healthData.setIgnitionCan(health.ignition_can);
- healthData.setControlsAllowed(health.controls_allowed);
- healthData.setGasInterceptorDetected(health.gas_interceptor_detected);
- healthData.setHasGps(is_pigeon);
- healthData.setCanRxErrs(health.can_rx_errs);
- healthData.setCanSendErrs(health.can_send_errs);
- healthData.setCanFwdErrs(health.can_fwd_errs);
- healthData.setGmlanSendErrs(health.gmlan_send_errs);
- healthData.setHwType(hw_type);
- healthData.setUsbPowerMode(cereal::HealthData::UsbPowerMode(health.usb_power_mode));
- healthData.setSafetyModel(cereal::CarParams::SafetyModel(health.safety_model));
- healthData.setFanSpeedRpm(fan_speed_rpm);
- healthData.setFaultStatus(cereal::HealthData::FaultStatus(health.fault_status));
- healthData.setPowerSaveEnabled((bool)(health.power_save_enabled));
-
- // Convert faults bitset to capnp list
- std::bitset fault_bits(health.faults);
- auto faults = healthData.initFaults(fault_bits.count());
-
- size_t i = 0;
- for (size_t f = size_t(cereal::HealthData::FaultType::RELAY_MALFUNCTION);
- f <= size_t(cereal::HealthData::FaultType::REGISTER_DIVERGENT); f++){
- if (fault_bits.test(f)) {
- faults.set(i, cereal::HealthData::FaultType(f));
- i++;
- }
- }
- // send to health
- auto words = capnp::messageToFlatArray(msg);
- auto bytes = words.asBytes();
- publisher->send((char*)bytes.begin(), bytes.size());
-
- // send heartbeat back to panda
- pthread_mutex_lock(&usb_lock);
- libusb_control_transfer(dev_handle, 0x40, 0xf3, 1, 0, NULL, 0, TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
-}
-
-
-void can_send(SubSocket *subscriber) {
- int err;
-
- // recv from sendcan
- Message * msg = subscriber->receive();
-
- auto amsg = kj::heapArray((msg->getSize() / sizeof(capnp::word)) + 1);
- memcpy(amsg.begin(), msg->getData(), msg->getSize());
-
- capnp::FlatArrayMessageReader cmsg(amsg);
- cereal::Event::Reader event = cmsg.getRoot();
- if (nanos_since_boot() - event.getLogMonoTime() > 1e9) {
- //Older than 1 second. Dont send.
- delete msg;
- return;
- }
- int msg_count = event.getSendcan().size();
-
- uint32_t *send = (uint32_t*)malloc(msg_count*0x10);
- memset(send, 0, msg_count*0x10);
-
- for (int i = 0; i < msg_count; i++) {
- auto cmsg = event.getSendcan()[i];
- if (cmsg.getAddress() >= 0x800) {
- // extended
- send[i*4] = (cmsg.getAddress() << 3) | 5;
- } else {
- // normal
- send[i*4] = (cmsg.getAddress() << 21) | 1;
- }
- assert(cmsg.getDat().size() <= 8);
- send[i*4+1] = cmsg.getDat().size() | (cmsg.getSrc() << 4);
- memcpy(&send[i*4+2], cmsg.getDat().begin(), cmsg.getDat().size());
- }
- // release msg
- delete msg;
-
- // send to board
- int sent;
- pthread_mutex_lock(&usb_lock);
-
-
- if (!fake_send) {
- do {
- // Try sending can messages. If the receive buffer on the panda is full it will NAK
- // and libusb will try again. After 5ms, it will time out. We will drop the messages.
- err = libusb_bulk_transfer(dev_handle, 3, (uint8_t*)send, msg_count*0x10, &sent, 5);
- if (err == LIBUSB_ERROR_TIMEOUT) {
- LOGW("Transmit buffer full");
- break;
- } else if (err != 0 || msg_count*0x10 != sent) {
- LOGW("Error");
- handle_usb_issue(err, __func__);
- }
- } while(err != 0);
+ int recv = panda->can_receive(event);
+ if (recv){
+ pm.send("can", msg);
}
-
- pthread_mutex_unlock(&usb_lock);
-
- // done
- free(send);
}
-// **** threads ****
-
-void *can_send_thread(void *crap) {
+void can_send_thread() {
LOGD("start send thread");
- // sendcan = 8017
Context * context = Context::create();
SubSocket * subscriber = SubSocket::create(context, "sendcan");
assert(subscriber != NULL);
+ subscriber->setTimeout(100);
+ // run as fast as messages come in
+ while (!do_exit && panda->connected) {
+ Message * msg = subscriber->receive();
- // drain sendcan to delete any stale messages from previous runs
- while (true){
- Message * msg = subscriber->receive(true);
- if (msg == NULL){
- break;
+ if (!msg){
+ if (errno == EINTR) {
+ do_exit = true;
+ }
+ continue;
}
+
+ auto amsg = kj::heapArray((msg->getSize() / sizeof(capnp::word)) + 1);
+ memcpy(amsg.begin(), msg->getData(), msg->getSize());
+
+ capnp::FlatArrayMessageReader cmsg(amsg);
+ cereal::Event::Reader event = cmsg.getRoot();
+
+ //Dont send if older than 1 second
+ if (nanos_since_boot() - event.getLogMonoTime() < 1e9) {
+ if (!fake_send){
+ panda->can_send(event.getSendcan());
+ }
+ }
+
delete msg;
}
- // run as fast as messages come in
- while (!do_exit) {
- can_send(subscriber);
- }
-
delete subscriber;
delete context;
- return NULL;
}
-void *can_recv_thread(void *crap) {
+void can_recv_thread() {
LOGD("start recv thread");
// can = 8006
- Context * c = Context::create();
- PubSocket * publisher = PubSocket::create(c, "can");
- assert(publisher != NULL);
+ PubMaster pm({"can"});
// run at 100hz
const uint64_t dt = 10000000ULL;
uint64_t next_frame_time = nanos_since_boot() + dt;
- while (!do_exit) {
- can_recv(publisher);
+ while (!do_exit && panda->connected) {
+ can_recv(pm);
uint64_t cur_time = nanos_since_boot();
int64_t remaining = next_frame_time - cur_time;
@@ -664,92 +264,186 @@ void *can_recv_thread(void *crap) {
next_frame_time += dt;
}
-
- delete publisher;
- delete c;
- return NULL;
}
-void *can_health_thread(void *crap) {
+void can_health_thread() {
LOGD("start health thread");
- // health = 8011
- Context * c = Context::create();
- PubSocket * publisher = PubSocket::create(c, "health");
- assert(publisher != NULL);
+ PubMaster pm({"health"});
- // run at 2hz
- while (!do_exit) {
- can_health(publisher);
+ uint32_t no_ignition_cnt = 0;
+ bool ignition_last = false;
+
+ // Broadcast empty health message when panda is not yet connected
+ while (!panda){
+ capnp::MallocMessageBuilder msg;
+ cereal::Event::Builder event = msg.initRoot();
+ event.setLogMonoTime(nanos_since_boot());
+ auto healthData = event.initHealth();
+
+ healthData.setHwType(cereal::HealthData::HwType::UNKNOWN);
+ pm.send("health", msg);
usleep(500*1000);
}
- delete publisher;
- delete c;
- return NULL;
-}
+ // run at 2hz
+ while (!do_exit && panda->connected) {
+ capnp::MallocMessageBuilder msg;
+ cereal::Event::Builder event = msg.initRoot();
+ event.setLogMonoTime(nanos_since_boot());
+ auto healthData = event.initHealth();
-void *hardware_control_thread(void *crap) {
- LOGD("start hardware control thread");
- Context * c = Context::create();
- SubSocket * thermal_sock = SubSocket::create(c, "thermal");
- SubSocket * front_frame_sock = SubSocket::create(c, "frontFrame");
- assert(thermal_sock != NULL);
- assert(front_frame_sock != NULL);
+ health_t health = panda->get_health();
- Poller * poller = Poller::create({thermal_sock, front_frame_sock});
+ if (spoofing_started) {
+ health.ignition_line = 1;
+ }
- // Wait for hardware type to be set.
- while (hw_type == cereal::HealthData::HwType::UNKNOWN){
- usleep(100*1000);
+ // Make sure CAN buses are live: safety_setter_thread does not work if Panda CAN are silent and there is only one other CAN node
+ if (health.safety_model == (uint8_t)(cereal::CarParams::SafetyModel::SILENT)) {
+ panda->set_safety_model(cereal::CarParams::SafetyModel::NO_OUTPUT);
+ }
+
+ bool ignition = ((health.ignition_line != 0) || (health.ignition_can != 0));
+
+ if (ignition) {
+ no_ignition_cnt = 0;
+ } else {
+ no_ignition_cnt += 1;
+ }
+
+#ifndef __x86_64__
+ bool power_save_desired = !ignition;
+ if (health.power_save_enabled != power_save_desired){
+ panda->set_power_saving(power_save_desired);
+ }
+
+ // set safety mode to NO_OUTPUT when car is off. ELM327 is an alternative if we want to leverage athenad/connect
+ if (!ignition && (health.safety_model != (uint8_t)(cereal::CarParams::SafetyModel::NO_OUTPUT))) {
+ panda->set_safety_model(cereal::CarParams::SafetyModel::NO_OUTPUT);
+ }
+#endif
+
+ // clear VIN, CarParams, and set new safety on car start
+ if (ignition && !ignition_last) {
+ int result = delete_db_value("CarVin");
+ assert((result == 0) || (result == ERR_NO_VALUE));
+ result = delete_db_value("CarParams");
+ assert((result == 0) || (result == ERR_NO_VALUE));
+
+ if (!safety_setter_thread_running) {
+ safety_setter_thread_running = true;
+ std::thread(safety_setter_thread).detach();
+ } else {
+ LOGW("Safety setter thread already running");
+ }
+ }
+
+ // Write to rtc once per minute when no ignition present
+ if ((panda->has_rtc) && !ignition && (no_ignition_cnt % 120 == 1)){
+ // Write time to RTC if it looks reasonable
+ struct tm sys_time = get_time();
+ if (time_valid(sys_time)){
+ panda->set_rtc(sys_time);
+ }
+ }
+
+ ignition_last = ignition;
+ uint16_t fan_speed_rpm = panda->get_fan_speed();
+
+ // set fields
+ healthData.setUptime(health.uptime);
+ healthData.setVoltage(health.voltage);
+ healthData.setCurrent(health.current);
+ healthData.setIgnitionLine(health.ignition_line);
+ healthData.setIgnitionCan(health.ignition_can);
+ healthData.setControlsAllowed(health.controls_allowed);
+ healthData.setGasInterceptorDetected(health.gas_interceptor_detected);
+ healthData.setHasGps(panda->is_pigeon);
+ healthData.setCanRxErrs(health.can_rx_errs);
+ healthData.setCanSendErrs(health.can_send_errs);
+ healthData.setCanFwdErrs(health.can_fwd_errs);
+ healthData.setGmlanSendErrs(health.gmlan_send_errs);
+ healthData.setHwType(panda->hw_type);
+ healthData.setUsbPowerMode(cereal::HealthData::UsbPowerMode(health.usb_power_mode));
+ healthData.setSafetyModel(cereal::CarParams::SafetyModel(health.safety_model));
+ healthData.setFanSpeedRpm(fan_speed_rpm);
+ healthData.setFaultStatus(cereal::HealthData::FaultStatus(health.fault_status));
+ healthData.setPowerSaveEnabled((bool)(health.power_save_enabled));
+
+ // Convert faults bitset to capnp list
+ std::bitset fault_bits(health.faults);
+ auto faults = healthData.initFaults(fault_bits.count());
+
+ size_t i = 0;
+ for (size_t f = size_t(cereal::HealthData::FaultType::RELAY_MALFUNCTION);
+ f <= size_t(cereal::HealthData::FaultType::INTERRUPT_RATE_TIM9); f++){
+ if (fault_bits.test(f)) {
+ faults.set(i, cereal::HealthData::FaultType(f));
+ i++;
+ }
+ }
+ pm.send("health", msg);
+ panda->send_heartbeat();
+ usleep(500*1000);
}
- // Only control fan speed on UNO
- if (hw_type != cereal::HealthData::HwType::UNO) return NULL;
+}
+
+void hardware_control_thread() {
+ LOGD("start hardware control thread");
+ SubMaster sm({"thermal", "frontFrame"});
+ // Only control fan speed on UNO
+ if (panda->hw_type != cereal::HealthData::HwType::UNO) return;
uint64_t last_front_frame_t = 0;
uint16_t prev_fan_speed = 999;
uint16_t ir_pwr = 0;
uint16_t prev_ir_pwr = 999;
+#ifdef QCOM
+ bool prev_charging_disabled = false;
+#endif
unsigned int cnt = 0;
- while (!do_exit) {
+ while (!do_exit && panda->connected) {
cnt++;
- for (auto sock : poller->poll(1000)){
- Message * msg = sock->receive();
- if (msg == NULL) continue;
-
- auto amsg = kj::heapArray((msg->getSize() / sizeof(capnp::word)) + 1);
- memcpy(amsg.begin(), msg->getData(), msg->getSize());
-
- delete msg;
-
- capnp::FlatArrayMessageReader cmsg(amsg);
- cereal::Event::Reader event = cmsg.getRoot();
-
- auto type = event.which();
- if(type == cereal::Event::THERMAL){
- uint16_t fan_speed = event.getThermal().getFanSpeed();
- if (fan_speed != prev_fan_speed || cnt % 100 == 0){
- pthread_mutex_lock(&usb_lock);
- libusb_control_transfer(dev_handle, 0x40, 0xb1, fan_speed, 0, NULL, 0, TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
+ sm.update(1000); // TODO: what happens if EINTR is sent while in sm.update?
+
+ if (sm.updated("thermal")){
+ // Fan speed
+ uint16_t fan_speed = sm["thermal"].getThermal().getFanSpeed();
+ if (fan_speed != prev_fan_speed || cnt % 100 == 0){
+ panda->set_fan_speed(fan_speed);
+ prev_fan_speed = fan_speed;
+ }
- prev_fan_speed = fan_speed;
- }
- } else if (type == cereal::Event::FRONT_FRAME){
- float cur_front_gain = event.getFrontFrame().getGainFrac();
- last_front_frame_t = event.getLogMonoTime();
-
- if (cur_front_gain <= CUTOFF_GAIN) {
- ir_pwr = 100.0 * MIN_IR_POWER;
- } else if (cur_front_gain > SATURATE_GAIN) {
- ir_pwr = 100.0 * MAX_IR_POWER;
+#ifdef QCOM
+ // Charging mode
+ bool charging_disabled = sm["thermal"].getThermal().getChargingDisabled();
+ if (charging_disabled != prev_charging_disabled){
+ if (charging_disabled){
+ panda->set_usb_power_mode(cereal::HealthData::UsbPowerMode::CLIENT);
+ LOGW("TURN OFF CHARGING!\n");
} else {
- ir_pwr = 100.0 * (MIN_IR_POWER + ((cur_front_gain - CUTOFF_GAIN) * (MAX_IR_POWER - MIN_IR_POWER) / (SATURATE_GAIN - CUTOFF_GAIN)));
+ panda->set_usb_power_mode(cereal::HealthData::UsbPowerMode::CDP);
+ LOGW("TURN ON CHARGING!\n");
}
+ prev_charging_disabled = charging_disabled;
+ }
+#endif
+ }
+ if (sm.updated("frontFrame")){
+ auto event = sm["frontFrame"];
+ int cur_integ_lines = event.getFrontFrame().getIntegLines();
+ last_front_frame_t = event.getLogMonoTime();
+
+ if (cur_integ_lines <= CUTOFF_IL) {
+ ir_pwr = 100.0 * MIN_IR_POWER;
+ } else if (cur_integ_lines > SATURATE_IL) {
+ ir_pwr = 100.0 * MAX_IR_POWER;
+ } else {
+ ir_pwr = 100.0 * (MIN_IR_POWER + ((cur_integ_lines - CUTOFF_IL) * (MAX_IR_POWER - MIN_IR_POWER) / (SATURATE_IL - CUTOFF_IL)));
}
}
-
// Disable ir_pwr on front frame timeout
uint64_t cur_t = nanos_since_boot();
if (cur_t - last_front_frame_t > 1e9){
@@ -757,182 +451,67 @@ void *hardware_control_thread(void *crap) {
}
if (ir_pwr != prev_ir_pwr || cnt % 100 == 0 || ir_pwr >= 50.0){
- pthread_mutex_lock(&usb_lock);
- libusb_control_transfer(dev_handle, 0x40, 0xb0, ir_pwr, 0, NULL, 0, TIMEOUT);
- pthread_mutex_unlock(&usb_lock);
+ panda->set_ir_pwr(ir_pwr);
prev_ir_pwr = ir_pwr;
}
}
-
- delete poller;
- delete thermal_sock;
- delete c;
-
- return NULL;
-}
-
-#define pigeon_send(x) _pigeon_send(x, sizeof(x)-1)
-
-void hexdump(unsigned char *d, int l) {
- for (int i = 0; i < l; i++) {
- if (i!=0 && i%0x10 == 0) printf("\n");
- printf("%2.2X ", d[i]);
- }
- printf("\n");
-}
-
-void _pigeon_send(const char *dat, int len) {
- int sent;
- unsigned char a[0x20];
- int err;
- a[0] = 1;
- for (int i=0; i();
event.setLogMonoTime(nanos_since_boot());
- auto ublox_raw = event.initUbloxRaw(alen);
- memcpy(ublox_raw.begin(), dat, alen);
+ auto ublox_raw = event.initUbloxRaw(dat.length());
+ memcpy(ublox_raw.begin(), dat.data(), dat.length());
- // send to ubloxRaw
- auto words = capnp::messageToFlatArray(msg);
- auto bytes = words.asBytes();
- publisher->send((char*)bytes.begin(), bytes.size());
+ pm.send("ubloxRaw", msg);
}
-void *pigeon_thread(void *crap) {
+void pigeon_thread() {
+ if (!panda->is_pigeon){ return; };
+
// ubloxRaw = 8042
- Context * context = Context::create();
- PubSocket * publisher = PubSocket::create(context, "ubloxRaw");
- assert(publisher != NULL);
-
- // run at ~100hz
- unsigned char dat[0x1000];
- uint64_t cnt = 0;
- while (!do_exit) {
- if (pigeon_needs_init) {
- pigeon_needs_init = false;
- pigeon_init();
- }
- int alen = 0;
- while (alen < 0xfc0) {
- pthread_mutex_lock(&usb_lock);
- int len = libusb_control_transfer(dev_handle, 0xc0, 0xe0, 1, 0, dat+alen, 0x40, TIMEOUT);
- if (len < 0) { handle_usb_issue(len, __func__); }
- pthread_mutex_unlock(&usb_lock);
- if (len <= 0) break;
-
- //printf("got %d\n", len);
- alen += len;
- }
- if (alen > 0) {
- if (dat[0] == (char)0x00){
+ PubMaster pm({"ubloxRaw"});
+
+#ifdef QCOM2
+ Pigeon * pigeon = Pigeon::connect("/dev/ttyHS0");
+#else
+ Pigeon * pigeon = Pigeon::connect(panda);
+#endif
+
+ pigeon->init();
+
+ while (!do_exit && panda->connected) {
+ std::string recv = pigeon->receive();
+ if (recv.length() > 0) {
+ if (recv[0] == (char)0x00){
LOGW("received invalid ublox message, resetting panda GPS");
- pigeon_init();
+ pigeon->init();
} else {
- pigeon_publish_raw(publisher, dat, alen);
+ pigeon_publish_raw(pm, recv);
}
}
- // 10ms
+ // 10ms - 100 Hz
usleep(10*1000);
- cnt++;
}
- delete publisher;
- delete context;
- return NULL;
+ delete pigeon;
}
-}
int main() {
int err;
LOGW("starting boardd");
- // set process priority
- err = set_realtime_priority(4);
- LOG("setpriority returns %d", err);
+ // set process priority and affinity
+ err = set_realtime_priority(54);
+ LOG("set priority returns %d", err);
+ err = set_core_affinity(3);
+ LOG("set affinity returns %d", err);
// check the environment
if (getenv("STARTED")) {
@@ -943,64 +522,23 @@ int main() {
fake_send = true;
}
- if (getenv("BOARDD_LOOPBACK")){
- loopback_can = true;
- }
-
- err = pthread_mutex_init(&usb_lock, NULL);
- assert(err == 0);
+ panda_set_power(true);
- // init libusb
- err = libusb_init(&ctx);
- assert(err == 0);
+ while (!do_exit){
+ std::vector threads;
+ threads.push_back(std::thread(can_health_thread));
-#if LIBUSB_API_VERSION >= 0x01000106
- libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
-#else
- libusb_set_debug(ctx, 3);
-#endif
-
- pthread_t can_health_thread_handle;
- err = pthread_create(&can_health_thread_handle, NULL,
- can_health_thread, NULL);
- assert(err == 0);
-
- // connect to the board
- pthread_mutex_lock(&usb_lock);
- usb_retry_connect();
- pthread_mutex_unlock(&usb_lock);
-
- // create threads
- pthread_t can_send_thread_handle;
- err = pthread_create(&can_send_thread_handle, NULL,
- can_send_thread, NULL);
- assert(err == 0);
-
- pthread_t can_recv_thread_handle;
- err = pthread_create(&can_recv_thread_handle, NULL,
- can_recv_thread, NULL);
- assert(err == 0);
-
- pthread_t hardware_control_thread_handle;
- err = pthread_create(&hardware_control_thread_handle, NULL,
- hardware_control_thread, NULL);
- assert(err == 0);
-
- // join threads
-
- err = pthread_join(can_recv_thread_handle, NULL);
- assert(err == 0);
-
- err = pthread_join(can_send_thread_handle, NULL);
- assert(err == 0);
-
- err = pthread_join(can_health_thread_handle, NULL);
- assert(err == 0);
+ // connect to the board
+ usb_retry_connect();
- //while (!do_exit) usleep(1000);
+ threads.push_back(std::thread(can_send_thread));
+ threads.push_back(std::thread(can_recv_thread));
+ threads.push_back(std::thread(hardware_control_thread));
+ threads.push_back(std::thread(pigeon_thread));
- // destruct libusb
+ for (auto &t : threads) t.join();
- libusb_close(dev_handle);
- libusb_exit(ctx);
+ delete panda;
+ panda = NULL;
+ }
}
diff --git a/selfdrive/boardd/boardd_setup.py b/selfdrive/boardd/boardd_setup.py
index cf71901cb6..4b08590183 100644
--- a/selfdrive/boardd/boardd_setup.py
+++ b/selfdrive/boardd/boardd_setup.py
@@ -1,15 +1,8 @@
-import subprocess
from distutils.core import Extension, setup
-
from Cython.Build import cythonize
from common.cython_hacks import BuildExtWithoutPlatformSuffix
-from common.basedir import BASEDIR
-import os
-
-PHONELIBS = os.path.join(BASEDIR, 'phonelibs')
-ARCH = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
libraries = ['can_list_to_can_capnp', 'capnp', 'kj']
setup(name='Boardd API Implementation',
diff --git a/selfdrive/boardd/panda.cc b/selfdrive/boardd/panda.cc
new file mode 100644
index 0000000000..7604bd7371
--- /dev/null
+++ b/selfdrive/boardd/panda.cc
@@ -0,0 +1,355 @@
+#include
+#include
+#include
+
+#include
+
+#include "common/swaglog.h"
+#include "common/gpio.h"
+
+#include "panda.h"
+
+void panda_set_power(bool power){
+#ifdef QCOM2
+ int err = 0;
+ err += gpio_init(GPIO_STM_RST_N, true);
+ err += gpio_init(GPIO_STM_BOOT0, true);
+ err += gpio_init(GPIO_HUB_RST_N, true);
+
+ err += gpio_set(GPIO_STM_RST_N, false);
+
+ // TODO: set hub somewhere else
+ err += gpio_set(GPIO_HUB_RST_N, true);
+ err += gpio_set(GPIO_STM_BOOT0, false);
+
+ usleep(100*1000); // 100 ms
+
+ err += gpio_set(GPIO_STM_RST_N, power);
+ assert(err == 0);
+#endif
+}
+
+Panda::Panda(){
+ int err;
+
+ err = pthread_mutex_init(&usb_lock, NULL);
+ if (err != 0) { goto fail; }
+
+ // init libusb
+ err = libusb_init(&ctx);
+ if (err != 0) { goto fail; }
+
+#if LIBUSB_API_VERSION >= 0x01000106
+ libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
+#else
+ libusb_set_debug(ctx, 3);
+#endif
+
+ dev_handle = libusb_open_device_with_vid_pid(ctx, 0xbbaa, 0xddcc);
+ if (dev_handle == NULL) { goto fail; }
+
+ if (libusb_kernel_driver_active(dev_handle, 0) == 1) {
+ libusb_detach_kernel_driver(dev_handle, 0);
+ }
+
+ err = libusb_set_configuration(dev_handle, 1);
+ if (err != 0) { goto fail; }
+
+ err = libusb_claim_interface(dev_handle, 0);
+ if (err != 0) { goto fail; }
+
+ hw_type = get_hw_type();
+ is_pigeon =
+ (hw_type == cereal::HealthData::HwType::GREY_PANDA) ||
+ (hw_type == cereal::HealthData::HwType::BLACK_PANDA) ||
+ (hw_type == cereal::HealthData::HwType::UNO) ||
+ (hw_type == cereal::HealthData::HwType::DOS);
+ has_rtc = (hw_type == cereal::HealthData::HwType::UNO) ||
+ (hw_type == cereal::HealthData::HwType::DOS);
+
+ return;
+
+fail:
+ cleanup();
+ throw std::runtime_error("Error connecting to panda");
+}
+
+Panda::~Panda(){
+ pthread_mutex_lock(&usb_lock);
+ cleanup();
+ connected = false;
+ pthread_mutex_unlock(&usb_lock);
+}
+
+void Panda::cleanup(){
+ if (dev_handle){
+ libusb_release_interface(dev_handle, 0);
+ libusb_close(dev_handle);
+ }
+
+ if (ctx) {
+ libusb_exit(ctx);
+ }
+}
+
+void Panda::handle_usb_issue(int err, const char func[]) {
+ LOGE_100("usb error %d \"%s\" in %s", err, libusb_strerror((enum libusb_error)err), func);
+ if (err == LIBUSB_ERROR_NO_DEVICE) {
+ LOGE("lost connection");
+ connected = false;
+ }
+ // TODO: check other errors, is simply retrying okay?
+}
+
+int Panda::usb_write(uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned int timeout) {
+ int err;
+ const uint8_t bmRequestType = LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE;
+
+ if (!connected){
+ return LIBUSB_ERROR_NO_DEVICE;
+ }
+
+ pthread_mutex_lock(&usb_lock);
+ do {
+ err = libusb_control_transfer(dev_handle, bmRequestType, bRequest, wValue, wIndex, NULL, 0, timeout);
+ if (err < 0) handle_usb_issue(err, __func__);
+ } while (err < 0 && connected);
+
+ pthread_mutex_unlock(&usb_lock);
+
+ return err;
+}
+
+int Panda::usb_read(uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout) {
+ int err;
+ const uint8_t bmRequestType = LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE;
+
+ pthread_mutex_lock(&usb_lock);
+ do {
+ err = libusb_control_transfer(dev_handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout);
+ if (err < 0) handle_usb_issue(err, __func__);
+ } while (err < 0 && connected);
+ pthread_mutex_unlock(&usb_lock);
+
+ return err;
+}
+
+int Panda::usb_bulk_write(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout) {
+ int err;
+ int transferred = 0;
+
+ if (!connected){
+ return 0;
+ }
+
+ pthread_mutex_lock(&usb_lock);
+ do {
+ // Try sending can messages. If the receive buffer on the panda is full it will NAK
+ // and libusb will try again. After 5ms, it will time out. We will drop the messages.
+ err = libusb_bulk_transfer(dev_handle, endpoint, data, length, &transferred, timeout);
+
+ if (err == LIBUSB_ERROR_TIMEOUT) {
+ LOGW("Transmit buffer full");
+ break;
+ } else if (err != 0 || length != transferred) {
+ handle_usb_issue(err, __func__);
+ }
+ } while(err != 0 && connected);
+
+ pthread_mutex_unlock(&usb_lock);
+ return transferred;
+}
+
+int Panda::usb_bulk_read(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout) {
+ int err;
+ int transferred = 0;
+
+ if (!connected){
+ return 0;
+ }
+
+ pthread_mutex_lock(&usb_lock);
+
+ do {
+ err = libusb_bulk_transfer(dev_handle, endpoint, data, length, &transferred, timeout);
+
+ if (err == LIBUSB_ERROR_TIMEOUT) {
+ break; // timeout is okay to exit, recv still happened
+ } else if (err == LIBUSB_ERROR_OVERFLOW) {
+ LOGE_100("overflow got 0x%x", transferred);
+ } else if (err != 0) {
+ handle_usb_issue(err, __func__);
+ }
+
+ } while(err != 0 && connected);
+
+ pthread_mutex_unlock(&usb_lock);
+
+ return transferred;
+}
+
+void Panda::set_safety_model(cereal::CarParams::SafetyModel safety_model, int safety_param){
+ usb_write(0xdc, (uint16_t)safety_model, safety_param);
+}
+
+cereal::HealthData::HwType Panda::get_hw_type() {
+ unsigned char hw_query[1] = {0};
+
+ usb_read(0xc1, 0, 0, hw_query, 1);
+ return (cereal::HealthData::HwType)(hw_query[0]);
+}
+
+void Panda::set_rtc(struct tm sys_time){
+ // tm struct has year defined as years since 1900
+ usb_write(0xa1, (uint16_t)(1900 + sys_time.tm_year), 0);
+ usb_write(0xa2, (uint16_t)(1 + sys_time.tm_mon), 0);
+ usb_write(0xa3, (uint16_t)sys_time.tm_mday, 0);
+ // usb_write(0xa4, (uint16_t)(1 + sys_time.tm_wday), 0);
+ usb_write(0xa5, (uint16_t)sys_time.tm_hour, 0);
+ usb_write(0xa6, (uint16_t)sys_time.tm_min, 0);
+ usb_write(0xa7, (uint16_t)sys_time.tm_sec, 0);
+}
+
+struct tm Panda::get_rtc(){
+ struct __attribute__((packed)) timestamp_t {
+ uint16_t year; // Starts at 0
+ uint8_t month;
+ uint8_t day;
+ uint8_t weekday;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+ } rtc_time = {0};
+
+ usb_read(0xa0, 0, 0, (unsigned char*)&rtc_time, sizeof(rtc_time));
+
+ struct tm new_time = { 0 };
+ new_time.tm_year = rtc_time.year - 1900; // tm struct has year defined as years since 1900
+ new_time.tm_mon = rtc_time.month - 1;
+ new_time.tm_mday = rtc_time.day;
+ new_time.tm_hour = rtc_time.hour;
+ new_time.tm_min = rtc_time.minute;
+ new_time.tm_sec = rtc_time.second;
+
+ return new_time;
+}
+
+void Panda::set_fan_speed(uint16_t fan_speed){
+ usb_write(0xb1, fan_speed, 0);
+}
+
+uint16_t Panda::get_fan_speed(){
+ uint16_t fan_speed_rpm = 0;
+ usb_read(0xb2, 0, 0, (unsigned char*)&fan_speed_rpm, sizeof(fan_speed_rpm));
+ return fan_speed_rpm;
+}
+
+void Panda::set_ir_pwr(uint16_t ir_pwr) {
+ usb_write(0xb0, ir_pwr, 0);
+}
+
+health_t Panda::get_health(){
+ health_t health {0};
+ usb_read(0xd2, 0, 0, (unsigned char*)&health, sizeof(health));
+ return health;
+}
+
+void Panda::set_loopback(bool loopback){
+ usb_write(0xe5, loopback, 0);
+}
+
+const char* Panda::get_firmware_version(){
+ const char* fw_sig_buf = new char[128]();
+
+ int read_1 = usb_read(0xd3, 0, 0, (unsigned char*)fw_sig_buf, 64);
+ int read_2 = usb_read(0xd4, 0, 0, (unsigned char*)fw_sig_buf + 64, 64);
+
+ if ((read_1 == 64) && (read_2 == 64)) {
+ return fw_sig_buf;
+ }
+
+ delete[] fw_sig_buf;
+ return NULL;
+}
+
+const char* Panda::get_serial(){
+ const char* serial_buf = new char[16]();
+
+ int err = usb_read(0xd0, 0, 0, (unsigned char*)serial_buf, 16);
+
+ if (err >= 0) {
+ return serial_buf;
+ }
+
+ delete[] serial_buf;
+ return NULL;
+
+}
+
+void Panda::set_power_saving(bool power_saving){
+ usb_write(0xe7, power_saving, 0);
+}
+
+void Panda::set_usb_power_mode(cereal::HealthData::UsbPowerMode power_mode){
+ usb_write(0xe6, (uint16_t)power_mode, 0);
+}
+
+void Panda::send_heartbeat(){
+ usb_write(0xf3, 1, 0);
+}
+
+void Panda::can_send(capnp::List::Reader can_data_list){
+ int msg_count = can_data_list.size();
+
+ uint32_t *send = new uint32_t[msg_count*0x10]();
+
+ for (int i = 0; i < msg_count; i++) {
+ auto cmsg = can_data_list[i];
+ if (cmsg.getAddress() >= 0x800) { // extended
+ send[i*4] = (cmsg.getAddress() << 3) | 5;
+ } else { // normal
+ send[i*4] = (cmsg.getAddress() << 21) | 1;
+ }
+ auto can_data = cmsg.getDat();
+ assert(can_data.size() <= 8);
+ send[i*4+1] = can_data.size() | (cmsg.getSrc() << 4);
+ memcpy(&send[i*4+2], can_data.begin(), can_data.size());
+ }
+
+ usb_bulk_write(3, (unsigned char*)send, msg_count*0x10, 5);
+
+ delete[] send;
+}
+
+int Panda::can_receive(cereal::Event::Builder &event){
+ uint32_t data[RECV_SIZE/4];
+ int recv = usb_bulk_read(0x81, (unsigned char*)data, RECV_SIZE);
+
+ // return if length is 0
+ if (recv <= 0) {
+ return 0;
+ } else if (recv == RECV_SIZE) {
+ LOGW("Receive buffer full");
+ }
+
+ size_t num_msg = recv / 0x10;
+ auto canData = event.initCan(num_msg);
+
+ // populate message
+ for (int i = 0; i < num_msg; i++) {
+ if (data[i*4] & 4) {
+ // extended
+ canData[i].setAddress(data[i*4] >> 3);
+ //printf("got extended: %x\n", data[i*4] >> 3);
+ } else {
+ // normal
+ canData[i].setAddress(data[i*4] >> 21);
+ }
+ canData[i].setBusTime(data[i*4+1] >> 16);
+ int len = data[i*4+1]&0xF;
+ canData[i].setDat(kj::arrayPtr((uint8_t*)&data[i*4+2], len));
+ canData[i].setSrc((data[i*4+1] >> 4) & 0xff);
+ }
+
+ return recv;
+}
diff --git a/selfdrive/boardd/panda.h b/selfdrive/boardd/panda.h
new file mode 100644
index 0000000000..c3e2dc981e
--- /dev/null
+++ b/selfdrive/boardd/panda.h
@@ -0,0 +1,81 @@
+#pragma once
+
+#include
+#include
+#include
+
+#include
+
+#include "cereal/gen/cpp/car.capnp.h"
+#include "cereal/gen/cpp/log.capnp.h"
+
+// double the FIFO size
+#define RECV_SIZE (0x1000)
+#define TIMEOUT 0
+
+// copied from panda/board/main.c
+struct __attribute__((packed)) health_t {
+ uint32_t uptime;
+ uint32_t voltage;
+ uint32_t current;
+ uint32_t can_rx_errs;
+ uint32_t can_send_errs;
+ uint32_t can_fwd_errs;
+ uint32_t gmlan_send_errs;
+ uint32_t faults;
+ uint8_t ignition_line;
+ uint8_t ignition_can;
+ uint8_t controls_allowed;
+ uint8_t gas_interceptor_detected;
+ uint8_t car_harness_status;
+ uint8_t usb_power_mode;
+ uint8_t safety_model;
+ uint8_t fault_status;
+ uint8_t power_save_enabled;
+};
+
+
+void panda_set_power(bool power);
+
+class Panda {
+ private:
+ libusb_context *ctx = NULL;
+ libusb_device_handle *dev_handle = NULL;
+ pthread_mutex_t usb_lock;
+ void handle_usb_issue(int err, const char func[]);
+ void cleanup();
+
+ public:
+ Panda();
+ ~Panda();
+
+ bool connected = true;
+ cereal::HealthData::HwType hw_type = cereal::HealthData::HwType::UNKNOWN;
+ bool is_pigeon = false;
+ bool has_rtc = false;
+
+ // HW communication
+ int usb_write(uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned int timeout=TIMEOUT);
+ int usb_read(uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout=TIMEOUT);
+ int usb_bulk_write(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout=TIMEOUT);
+ int usb_bulk_read(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout=TIMEOUT);
+
+ // Panda functionality
+ cereal::HealthData::HwType get_hw_type();
+ void set_safety_model(cereal::CarParams::SafetyModel safety_model, int safety_param=0);
+ void set_rtc(struct tm sys_time);
+ struct tm get_rtc();
+ void set_fan_speed(uint16_t fan_speed);
+ uint16_t get_fan_speed();
+ void set_ir_pwr(uint16_t ir_pwr);
+ health_t get_health();
+ void set_loopback(bool loopback);
+ const char* get_firmware_version();
+ const char* get_serial();
+ void set_power_saving(bool power_saving);
+ void set_usb_power_mode(cereal::HealthData::UsbPowerMode power_mode);
+ void send_heartbeat();
+ void can_send(capnp::List::Reader can_data_list);
+ int can_receive(cereal::Event::Builder &event);
+
+};
diff --git a/selfdrive/boardd/pigeon.cc b/selfdrive/boardd/pigeon.cc
new file mode 100644
index 0000000000..4ec7ebf8ce
--- /dev/null
+++ b/selfdrive/boardd/pigeon.cc
@@ -0,0 +1,226 @@
+#include
+#include
+#include
+#include
+#include
+
+#include "common/swaglog.h"
+#include "common/gpio.h"
+
+#include "pigeon.h"
+
+// Termios on macos doesn't define all baud rate constants
+#ifndef B460800
+#define B460800 0010004
+#endif
+
+using namespace std::string_literals;
+
+
+Pigeon * Pigeon::connect(Panda * p){
+ PandaPigeon * pigeon = new PandaPigeon();
+ pigeon->connect(p);
+
+ return pigeon;
+}
+
+Pigeon * Pigeon::connect(const char * tty){
+ TTYPigeon * pigeon = new TTYPigeon();
+ pigeon->connect(tty);
+
+ return pigeon;
+}
+
+void Pigeon::init() {
+ usleep(1000*1000);
+ LOGW("panda GPS start");
+
+ // power off pigeon
+ set_power(0);
+ usleep(100*1000);
+
+ // 9600 baud at init
+ set_baud(9600);
+
+ // power on pigeon
+ set_power(1);
+ usleep(500*1000);
+
+ // baud rate upping
+ send("\x24\x50\x55\x42\x58\x2C\x34\x31\x2C\x31\x2C\x30\x30\x30\x37\x2C\x30\x30\x30\x33\x2C\x34\x36\x30\x38\x30\x30\x2C\x30\x2A\x31\x35\x0D\x0A"s);
+ usleep(100*1000);
+
+ // set baud rate to 460800
+ set_baud(460800);
+ usleep(100*1000);
+
+ // init from ubloxd
+ // To generate this data, run test/ubloxd.py with the print statements enabled in the write function in panda/python/serial.py
+ send("\xB5\x62\x06\x00\x14\x00\x03\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x1E\x7F"s);
+ send("\xB5\x62\x06\x3E\x00\x00\x44\xD2"s);
+ send("\xB5\x62\x06\x00\x14\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x35"s);
+ send("\xB5\x62\x06\x00\x14\x00\x01\x00\x00\x00\xC0\x08\x00\x00\x00\x08\x07\x00\x01\x00\x01\x00\x00\x00\x00\x00\xF4\x80"s);
+ send("\xB5\x62\x06\x00\x14\x00\x04\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1D\x85"s);
+ send("\xB5\x62\x06\x00\x00\x00\x06\x18"s);
+ send("\xB5\x62\x06\x00\x01\x00\x01\x08\x22"s);
+ send("\xB5\x62\x06\x00\x01\x00\x02\x09\x23"s);
+ send("\xB5\x62\x06\x00\x01\x00\x03\x0A\x24"s);
+ send("\xB5\x62\x06\x08\x06\x00\x64\x00\x01\x00\x00\x00\x79\x10"s);
+ send("\xB5\x62\x06\x24\x24\x00\x05\x00\x04\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5A\x63"s);
+ send("\xB5\x62\x06\x1E\x14\x00\x00\x00\x00\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3C\x37"s);
+ send("\xB5\x62\x06\x24\x00\x00\x2A\x84"s);
+ send("\xB5\x62\x06\x23\x00\x00\x29\x81"s);
+ send("\xB5\x62\x06\x1E\x00\x00\x24\x72"s);
+ send("\xB5\x62\x06\x01\x03\x00\x01\x07\x01\x13\x51"s);
+ send("\xB5\x62\x06\x01\x03\x00\x02\x15\x01\x22\x70"s);
+ send("\xB5\x62\x06\x01\x03\x00\x02\x13\x01\x20\x6C"s);
+ send("\xB5\x62\x06\x01\x03\x00\x0A\x09\x01\x1E\x70"s);
+
+ LOGW("panda GPS on");
+}
+
+void PandaPigeon::connect(Panda * p) {
+ panda = p;
+}
+
+void PandaPigeon::set_baud(int baud) {
+ panda->usb_write(0xe2, 1, 0);
+ panda->usb_write(0xe4, 1, baud/300);
+}
+
+void PandaPigeon::send(std::string s) {
+ int len = s.length();
+ const char * dat = s.data();
+
+ unsigned char a[0x20+1];
+ a[0] = 1;
+ for (int i=0; iusb_bulk_write(2, a, ll+1);
+ }
+}
+
+std::string PandaPigeon::receive() {
+ std::string r;
+
+ while (true){
+ unsigned char dat[0x40];
+ int len = panda->usb_read(0xe0, 1, 0, dat, sizeof(dat));
+ if (len <= 0 || r.length() > 0x1000) break;
+ r.append((char*)dat, len);
+ }
+
+ return r;
+}
+
+void PandaPigeon::set_power(bool power) {
+ panda->usb_write(0xd9, power, 0);
+}
+
+PandaPigeon::~PandaPigeon(){
+}
+
+void handle_tty_issue(int err, const char func[]) {
+ LOGE_100("tty error %d \"%s\" in %s", err, strerror(err), func);
+}
+
+void TTYPigeon::connect(const char * tty) {
+ pigeon_tty_fd = open(tty, O_RDWR);
+ if (pigeon_tty_fd < 0){
+ handle_tty_issue(errno, __func__);
+ assert(pigeon_tty_fd >= 0);
+ }
+ assert(tcgetattr(pigeon_tty_fd, &pigeon_tty) == 0);
+
+ // configure tty
+ pigeon_tty.c_cflag &= ~PARENB; // disable parity
+ pigeon_tty.c_cflag &= ~CSTOPB; // single stop bit
+ pigeon_tty.c_cflag |= CS8; // 8 bits per byte
+ pigeon_tty.c_cflag &= ~CRTSCTS; // no RTS/CTS flow control
+ pigeon_tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
+ pigeon_tty.c_lflag &= ~ICANON; // disable canonical mode
+ pigeon_tty.c_lflag &= ~ISIG; // disable interpretation of INTR, QUIT and SUSP
+ pigeon_tty.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off software flow ctrl
+ pigeon_tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // disable any special handling of received bytes
+ pigeon_tty.c_oflag &= ~OPOST; // prevent special interpretation of output bytes
+ pigeon_tty.c_oflag &= ~ONLCR; // prevent conversion of newline to carriage return/line feed
+
+ // configure blocking behavior
+ pigeon_tty.c_cc[VMIN] = 0; // min amount of characters returned
+ pigeon_tty.c_cc[VTIME] = 0; // max blocking time in s/10 (0=inf)
+
+ assert(tcsetattr(pigeon_tty_fd, TCSANOW, &pigeon_tty) == 0);
+}
+
+void TTYPigeon::set_baud(int baud){
+ speed_t baud_const = 0;
+ switch(baud){
+ case 9600:
+ baud_const = B9600;
+ break;
+ case 460800:
+ baud_const = B460800;
+ break;
+ default:
+ assert(false);
+ }
+
+ // make sure everything is tx'ed before changing baud
+ assert(tcdrain(pigeon_tty_fd) == 0);
+
+ // change baud
+ assert(tcgetattr(pigeon_tty_fd, &pigeon_tty) == 0);
+ assert(cfsetspeed(&pigeon_tty, baud_const) == 0);
+ assert(tcsetattr(pigeon_tty_fd, TCSANOW, &pigeon_tty) == 0);
+
+ // flush
+ assert(tcflush(pigeon_tty_fd, TCIOFLUSH) == 0);
+}
+
+void TTYPigeon::send(std::string s) {
+ int len = s.length();
+ const char * dat = s.data();
+
+ int err = write(pigeon_tty_fd, dat, len);
+ if(err < 0) { handle_tty_issue(err, __func__); }
+ err = tcdrain(pigeon_tty_fd);
+ if(err < 0) { handle_tty_issue(err, __func__); }
+}
+
+std::string TTYPigeon::receive() {
+ std::string r;
+
+ while (true){
+ char dat[0x40];
+ int len = read(pigeon_tty_fd, dat, sizeof(dat));
+ if(len < 0) {
+ handle_tty_issue(len, __func__);
+ } else if (len == 0 || r.length() > 0x1000){
+ break;
+ } else {
+ r.append(dat, len);
+ }
+
+ }
+ return r;
+}
+
+void TTYPigeon::set_power(bool power){
+#ifdef QCOM2
+ int err = 0;
+ err += gpio_init(GPIO_UBLOX_RST_N, true);
+ err += gpio_init(GPIO_UBLOX_SAFEBOOT_N, true);
+ err += gpio_init(GPIO_UBLOX_PWR_EN, true);
+
+ err += gpio_set(GPIO_UBLOX_RST_N, power);
+ err += gpio_set(GPIO_UBLOX_SAFEBOOT_N, power);
+ err += gpio_set(GPIO_UBLOX_PWR_EN, power);
+ assert(err == 0);
+#endif
+}
+
+TTYPigeon::~TTYPigeon(){
+ close(pigeon_tty_fd);
+}
diff --git a/selfdrive/boardd/pigeon.h b/selfdrive/boardd/pigeon.h
new file mode 100644
index 0000000000..667ac70610
--- /dev/null
+++ b/selfdrive/boardd/pigeon.h
@@ -0,0 +1,43 @@
+#pragma once
+#include
+#include
+
+
+#include "panda.h"
+
+class Pigeon {
+ public:
+ static Pigeon* connect(Panda * p);
+ static Pigeon* connect(const char * tty);
+ virtual ~Pigeon(){};
+
+ void init();
+ virtual void set_baud(int baud) = 0;
+ virtual void send(std::string s) = 0;
+ virtual std::string receive() = 0;
+ virtual void set_power(bool power) = 0;
+};
+
+class PandaPigeon : public Pigeon {
+ Panda * panda = NULL;
+public:
+ ~PandaPigeon();
+ void connect(Panda * p);
+ void set_baud(int baud);
+ void send(std::string s);
+ std::string receive();
+ void set_power(bool power);
+};
+
+
+class TTYPigeon : public Pigeon {
+ int pigeon_tty_fd = -1;
+ struct termios pigeon_tty;
+public:
+ ~TTYPigeon();
+ void connect(const char* tty);
+ void set_baud(int baud);
+ void send(std::string s);
+ std::string receive();
+ void set_power(bool power);
+};
diff --git a/selfdrive/boardd/tests/boardd_old.py b/selfdrive/boardd/tests/boardd_old.py
index f6ca7eb87d..4fd2350bff 100755
--- a/selfdrive/boardd/tests/boardd_old.py
+++ b/selfdrive/boardd/tests/boardd_old.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
+# pylint: skip-file
-# This file is not used by OpenPilot. Only boardd.cc is used.
+# This file is not used by openpilot. Only boardd.cc is used.
# The python version is slower, but has more options for development.
# TODO: merge the extra functionalities of this file (like MOCK) in boardd.c and
@@ -21,7 +22,7 @@ SafetyModel = car.CarParams.SafetyModel
# USB is optional
try:
import usb1
- from usb1 import USBErrorIO, USBErrorOverflow #pylint: disable=no-name-in-module
+ from usb1 import USBErrorIO, USBErrorOverflow # pylint: disable=no-name-in-module
except Exception:
pass
@@ -57,7 +58,7 @@ def __parse_can_buffer(dat):
for j in range(0, len(dat), 0x10):
ddat = dat[j:j+0x10]
f1, f2 = struct.unpack("II", ddat[0:8])
- ret.append((f1 >> 21, f2>>16, ddat[8:8+(f2&0xF)], (f2>>4)&0xFF))
+ ret.append((f1 >> 21, f2 >> 16, ddat[8:8 + (f2 & 0xF)], (f2 >> 4) & 0xFF))
return ret
def can_send_many(arr):
@@ -138,7 +139,7 @@ def boardd_test_loop():
can_init()
cnt = 0
while 1:
- can_send_many([[0xbb,0,"\xaa\xaa\xaa\xaa",0], [0xaa,0,"\xaa\xaa\xaa\xaa"+struct.pack("!I", cnt),1]])
+ can_send_many([[0xbb, 0, "\xaa\xaa\xaa\xaa", 0], [0xaa, 0, "\xaa\xaa\xaa\xaa"+struct.pack("!I", cnt), 1]])
#can_send_many([[0xaa,0,"\xaa\xaa\xaa\xaa",0]])
#can_send_many([[0xaa,0,"\xaa\xaa\xaa\xaa",1]])
# recv @ 100hz
diff --git a/selfdrive/boardd/tests/replay_many.py b/selfdrive/boardd/tests/replay_many.py
index 7596b47a14..71db229a21 100755
--- a/selfdrive/boardd/tests/replay_many.py
+++ b/selfdrive/boardd/tests/replay_many.py
@@ -10,7 +10,7 @@ from multiprocessing import Pool
jungle = "JUNGLE" in os.environ
if jungle:
- from panda_jungle import PandaJungle # pylint: disable=import-error
+ from panda_jungle import PandaJungle # pylint: disable=import-error
import cereal.messaging as messaging
from selfdrive.boardd.boardd import can_capnp_to_can_list
@@ -56,7 +56,6 @@ if __name__ == "__main__":
serials = Panda.list()
num_senders = len(serials)
-
if num_senders == 0:
print("No senders found. Exiting")
sys.exit(1)
diff --git a/selfdrive/boardd/tests/test_boardd_api.py b/selfdrive/boardd/tests/test_boardd_api.py
index f41e1e3571..9386c7845e 100644
--- a/selfdrive/boardd/tests/test_boardd_api.py
+++ b/selfdrive/boardd/tests/test_boardd_api.py
@@ -12,7 +12,7 @@ import unittest
def generate_random_can_data_list():
can_list = []
cnt = random.randint(1, 64)
- for j in range(cnt):
+ for _ in range(cnt):
can_data = np.random.bytes(random.randint(1, 8))
can_list.append([random.randint(0, 128), random.randint(0, 128), can_data, random.randint(0, 128)])
return can_list, cnt
@@ -54,18 +54,18 @@ class TestBoarddApiMethods(unittest.TestCase):
self.assertEqual(getattr(ev.can[i], attr, 'new'), getattr(ev_old.can[i], attr, 'old'))
def test_performance(self):
- can_list, cnt = generate_random_can_data_list()
+ can_list, _ = generate_random_can_data_list()
recursions = 1000
n1 = sec_since_boot()
- for i in range(recursions):
+ for _ in range(recursions):
boardd_old.can_list_to_can_capnp(can_list, 'sendcan').to_bytes()
n2 = sec_since_boot()
elapsed_old = n2 - n1
# print('Old API, elapsed time: {} secs'.format(elapsed_old))
n1 = sec_since_boot()
- for i in range(recursions):
+ for _ in range(recursions):
boardd.can_list_to_can_capnp(can_list)
n2 = sec_since_boot()
elapsed_new = n2 - n1
diff --git a/selfdrive/boardd/tests/test_boardd_loopback.py b/selfdrive/boardd/tests/test_boardd_loopback.py
index cb88776a0a..d6c110bbbe 100755
--- a/selfdrive/boardd/tests/test_boardd_loopback.py
+++ b/selfdrive/boardd/tests/test_boardd_loopback.py
@@ -1,47 +1,87 @@
#!/usr/bin/env python3
-"""Run boardd with the BOARDD_LOOPBACK envvar before running this test."""
-
import os
import random
import time
+from collections import defaultdict
+from functools import wraps
+import cereal.messaging as messaging
+from cereal import car
+from common.basedir import PARAMS
+from common.android import ANDROID
+from common.params import Params
+from common.spinner import Spinner
+from panda import Panda
from selfdrive.boardd.boardd import can_list_to_can_capnp
-from cereal.messaging import drain_sock, pub_sock, sub_sock
+from selfdrive.car import make_can_msg
+from selfdrive.test.helpers import with_processes
+
+
+def reset_panda(fn):
+ @wraps(fn)
+ def wrapper():
+ p = Panda()
+ for i in [0, 1, 2, 0xFFFF]:
+ p.can_clear(i)
+ p.reset()
+ p.close()
+ fn()
+ return wrapper
+
+os.environ['STARTED'] = '1'
+os.environ['BOARDD_LOOPBACK'] = '1'
+os.environ['PARAMS_PATH'] = PARAMS
-def get_test_string():
- return b"test"+os.urandom(10)
+@reset_panda
+@with_processes(['boardd'])
+def test_boardd_loopback():
+ # wait for boardd to init
+ spinner = Spinner(noop=(not ANDROID))
+ time.sleep(2)
-BUS = 0
+ # boardd blocks on CarVin and CarParams
+ cp = car.CarParams.new_message()
+ cp.safetyModel = car.CarParams.SafetyModel.allOutput
+ Params().put("CarVin", b"0"*17)
+ Params().put("CarParams", cp.to_bytes())
-def main():
- rcv = sub_sock('can') # port 8006
- snd = pub_sock('sendcan') # port 8017
- time.sleep(0.3) # wait to bind before send/recv
+ sendcan = messaging.pub_sock('sendcan')
+ can = messaging.sub_sock('can', conflate=False, timeout=100)
- for i in range(10):
- print("Loop %d" % i)
- at = random.randint(1024, 2000)
- st = get_test_string()[0:8]
- snd.send(can_list_to_can_capnp([[at, 0, st, 0]], msgtype='sendcan').to_bytes())
- time.sleep(0.1)
- res = drain_sock(rcv, True)
- assert len(res) == 1
+ time.sleep(1)
- res = res[0].can
- assert len(res) == 2
+ n = 1000
+ for i in range(n):
+ spinner.update(f"boardd loopback {i}/{n}")
- msg0, msg1 = res
+ sent_msgs = defaultdict(set)
+ for _ in range(random.randrange(10)):
+ to_send = []
+ for __ in range(random.randrange(100)):
+ bus = random.randrange(3)
+ addr = random.randrange(1, 1<<29)
+ dat = bytes([random.getrandbits(8) for _ in range(random.randrange(1, 9))])
+ sent_msgs[bus].add((addr, dat))
+ to_send.append(make_can_msg(addr, dat, bus))
+ sendcan.send(can_list_to_can_capnp(to_send, msgtype='sendcan'))
- assert msg0.dat == st
- assert msg1.dat == st
+ max_recv = 10
+ while max_recv > 0 and any(len(sent_msgs[bus]) for bus in range(3)):
+ recvd = messaging.drain_sock(can, wait_for_one=True)
+ for msg in recvd:
+ for m in msg.can:
+ if m.src >= 128:
+ k = (m.address, m.dat)
+ assert k in sent_msgs[m.src-128]
+ sent_msgs[m.src-128].discard(k)
+ max_recv -= 1
- assert msg0.address == at
- assert msg1.address == at
+ # if a set isn't empty, messages got dropped
+ for bus in range(3):
+ assert not len(sent_msgs[bus]), f"loop {i}: bus {bus} missing {len(sent_msgs[bus])} messages"
- assert msg0.src == 0x80 | BUS
- assert msg1.src == BUS
+ spinner.close()
- print("Success")
if __name__ == "__main__":
- main()
+ test_boardd_loopback()
diff --git a/selfdrive/camerad/SConscript b/selfdrive/camerad/SConscript
index 0fc320fb92..3a706e2251 100644
--- a/selfdrive/camerad/SConscript
+++ b/selfdrive/camerad/SConscript
@@ -1,10 +1,13 @@
-Import('env', 'arch', 'messaging', 'common', 'gpucommon', 'visionipc', 'cereal', 'webcam')
+Import('env', 'arch', 'cereal', 'messaging', 'common', 'gpucommon', 'visionipc', 'webcam', 'QCOM_REPLAY')
-libs = ['m', 'pthread', common, 'jpeg', cereal, 'OpenCL', messaging, 'czmq', 'zmq', 'capnp', 'kj', visionipc, gpucommon]
+libs = ['m', 'pthread', common, 'jpeg', 'OpenCL', cereal, messaging, 'czmq', 'zmq', 'capnp', 'kj', visionipc, gpucommon]
if arch == "aarch64":
libs += ['gsl', 'CB', 'adreno_utils', 'EGL', 'GLESv3', 'cutils', 'ui']
- cameras = ['cameras/camera_qcom.cc']
+ if QCOM_REPLAY:
+ cameras = ['cameras/camera_frame_stream.cc']
+ else:
+ cameras = ['cameras/camera_qcom.cc']
elif arch == "larch64":
libs += []
cameras = ['cameras/camera_qcom2.c']
@@ -23,6 +26,10 @@ else:
else:
libs += []
cameras = ['cameras/camera_frame_stream.cc']
+ if arch == "Darwin":
+ del libs[libs.index('OpenCL')]
+ env = env.Clone()
+ env['FRAMEWORKS'] = ['OpenCL']
env.SharedLibrary('snapshot/visionipc',
["#selfdrive/common/visionipc.c", "#selfdrive/common/ipc.c"])
diff --git a/selfdrive/camerad/cameras/camera_frame_stream.cc b/selfdrive/camerad/cameras/camera_frame_stream.cc
index 00385ac75f..9a4263103d 100644
--- a/selfdrive/camerad/cameras/camera_frame_stream.cc
+++ b/selfdrive/camerad/cameras/camera_frame_stream.cc
@@ -1,15 +1,11 @@
#include "camera_frame_stream.h"
-#include
#include
-#include
#include
#include
#include
#include
-#include
-#include "cereal/gen/cpp/log.capnp.h"
#include "messaging.hpp"
#include "common/util.h"
@@ -36,9 +32,7 @@ void camera_close(CameraState *s) {
tbuffer_stop(&s->camera_tb);
}
-void camera_release_buffer(void *cookie, int buf_idx) {
- CameraState *s = static_cast(cookie);
-}
+void camera_release_buffer(void *cookie, int buf_idx) {}
void camera_init(CameraState *s, int camera_id, unsigned int fps) {
assert(camera_id < ARRAYSIZE(cameras_supported));
@@ -52,23 +46,15 @@ void camera_init(CameraState *s, int camera_id, unsigned int fps) {
}
void run_frame_stream(MultiCameraState *s) {
- int err;
- Context * context = Context::create();
- SubSocket * recorder_sock = SubSocket::create(context, "frame");
- assert(recorder_sock != NULL);
+ SubMaster sm({"frame"});
CameraState *const rear_camera = &s->rear;
auto *tb = &rear_camera->camera_tb;
while (!do_exit) {
- Message * msg = recorder_sock->receive();
-
- auto amsg = kj::heapArray((msg->getSize() / sizeof(capnp::word)) + 1);
- memcpy(amsg.begin(), msg->getData(), msg->getSize());
+ if (sm.update(1000) == 0) continue;
- capnp::FlatArrayMessageReader cmsg(amsg);
- cereal::Event::Reader event = cmsg.getRoot();
- auto frame = event.getFrame();
+ auto frame = sm["frame"].getFrame();
const int buf_idx = tbuffer_select(tb);
rear_camera->camera_bufs_metadata[buf_idx] = {
@@ -81,35 +67,21 @@ void run_frame_stream(MultiCameraState *s) {
cl_command_queue q = rear_camera->camera_bufs[buf_idx].copy_q;
cl_mem yuv_cl = rear_camera->camera_bufs[buf_idx].buf_cl;
- cl_event map_event;
- void *yuv_buf = (void *)clEnqueueMapBuffer(q, yuv_cl, CL_TRUE,
- CL_MAP_WRITE, 0, frame.getImage().size(),
- 0, NULL, &map_event, &err);
- assert(err == 0);
- clWaitForEvents(1, &map_event);
- clReleaseEvent(map_event);
- memcpy(yuv_buf, frame.getImage().begin(), frame.getImage().size());
-
- clEnqueueUnmapMemObject(q, yuv_cl, yuv_buf, 0, NULL, &map_event);
- clWaitForEvents(1, &map_event);
- clReleaseEvent(map_event);
- tbuffer_dispatch(tb, buf_idx);
- delete msg;
+ clEnqueueWriteBuffer(q, yuv_cl, CL_TRUE, 0, frame.getImage().size(), frame.getImage().begin(), 0, NULL, NULL);
+ tbuffer_dispatch(tb, buf_idx);
}
- delete recorder_sock;
- delete context;
}
} // namespace
CameraInfo cameras_supported[CAMERA_ID_MAX] = {
[CAMERA_ID_IMX298] = {
- .frame_width = FRAME_WIDTH,
- .frame_height = FRAME_HEIGHT,
- .frame_stride = FRAME_WIDTH*3,
- .bayer = false,
- .bayer_flip = false,
+ .frame_width = FRAME_WIDTH,
+ .frame_height = FRAME_HEIGHT,
+ .frame_stride = FRAME_WIDTH*3,
+ .bayer = false,
+ .bayer_flip = false,
},
[CAMERA_ID_OV8865] = {
.frame_width = 1632,
@@ -122,8 +94,6 @@ CameraInfo cameras_supported[CAMERA_ID_MAX] = {
};
void cameras_init(MultiCameraState *s) {
- memset(s, 0, sizeof(*s));
-
camera_init(&s->rear, CAMERA_ID_IMX298, 20);
s->rear.transform = (mat3){{
1.0, 0.0, 0.0,
@@ -146,7 +116,6 @@ void cameras_open(MultiCameraState *s, VisionBuf *camera_bufs_rear,
VisionBuf *camera_bufs_front) {
assert(camera_bufs_rear);
assert(camera_bufs_front);
- int err;
// LOG("*** open front ***");
camera_open(&s->front, camera_bufs_front, false);
diff --git a/selfdrive/camerad/cameras/camera_qcom.cc b/selfdrive/camerad/cameras/camera_qcom.cc
index a47fd586e6..4e8958818c 100644
--- a/selfdrive/camerad/cameras/camera_qcom.cc
+++ b/selfdrive/camerad/cameras/camera_qcom.cc
@@ -12,7 +12,6 @@
#include
#include
-#include
#include
#include "msmb_isp.h"
#include "msmb_ispif.h"
@@ -108,8 +107,6 @@ static void camera_release_buffer(void* cookie, int buf_idx) {
static void camera_init(CameraState *s, int camera_id, int camera_num,
uint32_t pixel_clock, uint32_t line_length_pclk,
unsigned int max_gain, unsigned int fps) {
- memset(s, 0, sizeof(*s));
-
s->camera_num = camera_num;
s->camera_id = camera_id;
@@ -123,9 +120,11 @@ static void camera_init(CameraState *s, int camera_id, int camera_num,
s->max_gain = max_gain;
s->fps = fps;
- zsock_t *ops_sock = zsock_new_push(">inproc://cameraops");
- assert(ops_sock);
- s->ops_sock = zsock_resolve(ops_sock);
+ s->self_recover = 0;
+
+ s->ops_sock = zsock_new_push(">inproc://cameraops");
+ assert(s->ops_sock);
+ s->ops_sock_handle = zsock_resolve(s->ops_sock);
tbuffer_init2(&s->camera_tb, FRAME_BUF_COUNT, "frame",
camera_release_buffer, s);
@@ -161,16 +160,6 @@ static int imx298_apply_exposure(CameraState *s, int gain, int integ_lines, int
//printf("%5d/%5d %5d %f\n", s->cur_integ_lines, s->cur_frame_length, analog_gain, s->digital_gain);
- int digital_gain = 0x100;
-
- float white_balance[] = {0.4609375, 1.0, 0.546875};
- //float white_balance[] = {1.0, 1.0, 1.0};
-
- int digital_gain_gr = digital_gain / white_balance[1];
- int digital_gain_gb = digital_gain / white_balance[1];
- int digital_gain_r = digital_gain / white_balance[0];
- int digital_gain_b = digital_gain / white_balance[2];
-
struct msm_camera_i2c_reg_array reg_array[] = {
// REG_HOLD
{0x104,0x1,0},
@@ -201,23 +190,24 @@ static int imx298_apply_exposure(CameraState *s, int gain, int integ_lines, int
return err;
}
-static inline int ov8865_get_coarse_gain(int gain) {
- static const int gains[] = {0, 256, 384, 448, 480};
- int i;
+static int ov8865_apply_exposure(CameraState *s, int gain, int integ_lines, int frame_length) {
+ //printf("front camera: %d %d %d\n", gain, integ_lines, frame_length);
+ int err, coarse_gain_bitmap, fine_gain_bitmap;
+ // get bitmaps from iso
+ static const int gains[] = {0, 100, 200, 400, 800};
+ int i;
for (i = 1; i < ARRAYSIZE(gains); i++) {
if (gain >= gains[i - 1] && gain < gains[i])
break;
}
+ int coarse_gain = i - 1;
+ float fine_gain = (gain - gains[coarse_gain])/(float)(gains[coarse_gain+1]-gains[coarse_gain]);
+ coarse_gain_bitmap = (1 << coarse_gain) - 1;
+ fine_gain_bitmap = ((int)(16*fine_gain) << 3) + 128; // 7th is always 1, 0-2nd are always 0
- return i - 1;
-}
-
-static int ov8865_apply_exposure(CameraState *s, int gain, int integ_lines, int frame_length) {
- //printf("front camera: %d %d %d\n", gain, integ_lines, frame_length);
- int err, gain_bitmap;
- gain_bitmap = (1 << ov8865_get_coarse_gain(gain)) - 1;
integ_lines *= 16; // The exposure value in reg is in 16ths of a line
+
struct msm_camera_i2c_reg_array reg_array[] = {
//{0x104,0x1,0},
@@ -228,7 +218,7 @@ static int ov8865_apply_exposure(CameraState *s, int gain, int integ_lines, int
// AEC MANUAL
{0x3503, 0x4, 0},
// AEC GAIN
- {0x3508, (uint16_t)(gain_bitmap), 0}, {0x3509, 0xf8, 0},
+ {0x3508, (uint16_t)(coarse_gain_bitmap), 0}, {0x3509, (uint16_t)(fine_gain_bitmap), 0},
//{0x104,0x0,0},
};
@@ -269,8 +259,6 @@ static int imx179_s5k3p8sp_apply_exposure(CameraState *s, int gain, int integ_li
}
void cameras_init(MultiCameraState *s) {
- memset(s, 0, sizeof(*s));
-
char project_name[1024] = {0};
property_get("ro.boot.project_name", project_name, "");
@@ -386,7 +374,10 @@ static void set_exposure(CameraState *s, float exposure_frac, float gain_frac) {
|| integ_lines != s->cur_integ_lines
|| frame_length != s->cur_frame_length) {
- if (s->apply_exposure) {
+ if (s->apply_exposure == ov8865_apply_exposure) {
+ gain = 800 * gain_frac; // ISO
+ err = s->apply_exposure(s, gain, integ_lines, frame_length);
+ } else if (s->apply_exposure) {
err = s->apply_exposure(s, gain, integ_lines, frame_length);
}
@@ -401,7 +392,9 @@ static void set_exposure(CameraState *s, float exposure_frac, float gain_frac) {
if (err == 0) {
s->cur_exposure_frac = exposure_frac;
+ pthread_mutex_lock(&s->frame_info_lock);
s->cur_gain_frac = gain_frac;
+ pthread_mutex_unlock(&s->frame_info_lock);
}
//LOGD("set exposure: %f %f - %d", exposure_frac, gain_frac, err);
@@ -409,19 +402,44 @@ static void set_exposure(CameraState *s, float exposure_frac, float gain_frac) {
static void do_autoexposure(CameraState *s, float grey_frac) {
const float target_grey = 0.3;
+ if (s->apply_exposure == ov8865_apply_exposure) {
+ // gain limits downstream
+ const float gain_frac_min = 0.015625;
+ const float gain_frac_max = 1.0;
+ // exposure time limits
+ unsigned int frame_length = s->pixel_clock / s->line_length_pclk / s->fps;
+ const unsigned int exposure_time_min = 16;
+ const unsigned int exposure_time_max = frame_length - 11; // copied from set_exposure()
+
+ float cur_gain_frac = s->cur_gain_frac;
+ float exposure_factor = pow(1.05, (target_grey - grey_frac) / 0.05);
+ if (cur_gain_frac > 0.125 && exposure_factor < 1) {
+ cur_gain_frac *= exposure_factor;
+ } else if (s->cur_integ_lines * exposure_factor <= exposure_time_max && s->cur_integ_lines * exposure_factor >= exposure_time_min) { // adjust exposure time first
+ s->cur_exposure_frac *= exposure_factor;
+ } else if (cur_gain_frac * exposure_factor <= gain_frac_max && cur_gain_frac * exposure_factor >= gain_frac_min) {
+ cur_gain_frac *= exposure_factor;
+ }
+ pthread_mutex_lock(&s->frame_info_lock);
+ s->cur_gain_frac = cur_gain_frac;
+ pthread_mutex_unlock(&s->frame_info_lock);
+
+ set_exposure(s, s->cur_exposure_frac, cur_gain_frac);
+
+ } else { // keep the old for others
+ float new_exposure = s->cur_exposure_frac;
+ new_exposure *= pow(1.05, (target_grey - grey_frac) / 0.05 );
+ //LOGD("diff %f: %f to %f", target_grey - grey_frac, s->cur_exposure_frac, new_exposure);
+
+ float new_gain = s->cur_gain_frac;
+ if (new_exposure < 0.10) {
+ new_gain *= 0.95;
+ } else if (new_exposure > 0.40) {
+ new_gain *= 1.05;
+ }
- float new_exposure = s->cur_exposure_frac;
- new_exposure *= pow(1.05, (target_grey - grey_frac) / 0.05 );
- //LOGD("diff %f: %f to %f", target_grey - grey_frac, s->cur_exposure_frac, new_exposure);
-
- float new_gain = s->cur_gain_frac;
- if (new_exposure < 0.10) {
- new_gain *= 0.95;
- } else if (new_exposure > 0.40) {
- new_gain *= 1.05;
+ set_exposure(s, new_exposure, new_gain);
}
-
- set_exposure(s, new_exposure, new_gain);
}
void camera_autoexposure(CameraState *s, float grey_frac) {
@@ -431,7 +449,7 @@ void camera_autoexposure(CameraState *s, float grey_frac) {
.grey_frac = grey_frac,
};
- zmq_send(s->ops_sock, &msg, sizeof(msg), ZMQ_DONTWAIT);
+ zmq_send(s->ops_sock_handle, &msg, sizeof(msg), ZMQ_DONTWAIT);
}
static uint8_t* get_eeprom(int eeprom_fd, size_t *out_len) {
@@ -1745,8 +1763,13 @@ static void parse_autofocus(CameraState *s, uint8_t *d) {
avg_focus += s->focus[i];
}
}
+ // self recover override
+ if (s->self_recover > 1) {
+ s->focus_err = 200 * ((s->self_recover % 2 == 0) ? 1:-1); // far for even numbers, close for odd
+ s->self_recover -= 2;
+ return;
+ }
- //printf("\n");
if (good_count < 4) {
s->focus_err = nan("");
return;
@@ -1770,18 +1793,19 @@ static void do_autofocus(CameraState *s) {
float err = s->focus_err;
float sag = (s->last_sag_acc_z/9.8) * 128;
- const int dac_up = s->device == DEVICE_LP3? 634:456;
- const int dac_down = s->device == DEVICE_LP3? 366:224;
+ const int dac_up = s->device == DEVICE_LP3? LP3_AF_DAC_UP:OP3T_AF_DAC_UP;
+ const int dac_down = s->device == DEVICE_LP3? LP3_AF_DAC_DOWN:OP3T_AF_DAC_DOWN;
+ float lens_true_pos = s->lens_true_pos;
if (!isnan(err)) {
// learn lens_true_pos
- s->lens_true_pos -= err*focus_kp;
+ lens_true_pos -= err*focus_kp;
}
// stay off the walls
- s->lens_true_pos = clamp(s->lens_true_pos, dac_down, dac_up);
-
- int target = clamp(s->lens_true_pos - sag, dac_down, dac_up);
+ lens_true_pos = clamp(lens_true_pos, dac_down, dac_up);
+ int target = clamp(lens_true_pos - sag, dac_down, dac_up);
+ s->lens_true_pos = lens_true_pos;
/*char debug[4096];
char *pdebug = debug;
@@ -1934,6 +1958,8 @@ static void camera_close(CameraState *s) {
}
free(s->eeprom);
+
+ zsock_destroy(&s->ops_sock);
}
@@ -1980,43 +2006,6 @@ static FrameMetadata get_frame_metadata(CameraState *s, uint32_t frame_id) {
};
}
-static bool acceleration_from_sensor_sock(void *sock, float *vs) {
- int err;
- bool ret = false;
- zmq_msg_t msg;
- err = zmq_msg_init(&msg);
- assert(err == 0);
-
- err = zmq_msg_recv(&msg, sock, 0);
- assert(err >= 0);
-
- void *data = zmq_msg_data(&msg);
- size_t size = zmq_msg_size(&msg);
-
- auto amsg = kj::heapArray(size / sizeof(capnp::word) + 1);
- memcpy(amsg.begin(), data, size);
- capnp::FlatArrayMessageReader cmsg(amsg);
- auto event = cmsg.getRoot();
- if (event.which() == cereal::Event::SENSOR_EVENTS) {
- auto sensor_events = event.getSensorEvents();
- for (auto sensor_event : sensor_events) {
- if (sensor_event.which() == cereal::SensorEventData::ACCELERATION) {
- auto v = sensor_event.getAcceleration().getV();
- if (v.size() < 3) {
- continue; //wtf
- }
- for (int j = 0; j < 3; j++) {
- vs[j] = v[j];
- }
- ret = true;
- break;
- }
- }
- }
- zmq_msg_close(&msg);
- return ret;
-}
-
static void ops_term() {
zsock_t *ops_sock = zsock_new_push(">inproc://cameraops");
assert(ops_sock);
@@ -2036,66 +2025,85 @@ static void* ops_thread(void* arg) {
zsock_t *cameraops = zsock_new_pull("@inproc://cameraops");
assert(cameraops);
- zsock_t *sensor_sock = zsock_new_sub(">tcp://127.0.0.1:8003", "");
- assert(sensor_sock);
-
zsock_t *terminate = zsock_new_sub(">inproc://terminate", "");
assert(terminate);
- zpoller_t *poller = zpoller_new(cameraops, sensor_sock, terminate, NULL);
+ zpoller_t *poller = zpoller_new(cameraops, terminate, NULL);
assert(poller);
- while (!do_exit) {
+ SubMaster sm({"sensorEvents"}); // msgq submaster
+ while (!do_exit) {
+ // zmq handling
zsock_t *which = (zsock_t*)zpoller_wait(poller, -1);
- if (which == terminate || which == NULL) {
+ if (which == terminate) {
break;
- }
- void* sockraw = zsock_resolve(which);
-
- if (which == cameraops) {
- zmq_msg_t msg;
- err = zmq_msg_init(&msg);
- assert(err == 0);
-
- err = zmq_msg_recv(&msg, sockraw, 0);
- assert(err >= 0);
-
- CameraMsg cmsg;
- if (zmq_msg_size(&msg) == sizeof(cmsg)) {
- memcpy(&cmsg, zmq_msg_data(&msg), zmq_msg_size(&msg));
-
- //LOGD("cameraops %d", cmsg.type);
+ } else if (which != NULL) {
+ void* sockraw = zsock_resolve(which);
+
+ if (which == cameraops) {
+ zmq_msg_t msg;
+ err = zmq_msg_init(&msg);
+ assert(err == 0);
+
+ err = zmq_msg_recv(&msg, sockraw, 0);
+ if (err >= 0) {
+ CameraMsg cmsg;
+ if (zmq_msg_size(&msg) == sizeof(cmsg)) {
+ memcpy(&cmsg, zmq_msg_data(&msg), zmq_msg_size(&msg));
+
+ //LOGD("cameraops %d", cmsg.type);
+
+ if (cmsg.type == CAMERA_MSG_AUTOEXPOSE) {
+ if (cmsg.camera_num == 0) {
+ do_autoexposure(&s->rear, cmsg.grey_frac);
+ do_autofocus(&s->rear);
+ } else {
+ do_autoexposure(&s->front, cmsg.grey_frac);
+ }
+ } else if (cmsg.type == -1) {
+ break;
+ }
+ }
+ } else {
+ // skip if zmq is interrupted by msgq
+ int err_no = zmq_errno();
+ assert(err_no == EINTR || err_no == EAGAIN);
+ }
- if (cmsg.type == CAMERA_MSG_AUTOEXPOSE) {
- if (cmsg.camera_num == 0) {
- do_autoexposure(&s->rear, cmsg.grey_frac);
- do_autofocus(&s->rear);
- } else {
- do_autoexposure(&s->front, cmsg.grey_frac);
+ zmq_msg_close(&msg);
+ }
+ }
+ // msgq handling
+ if (sm.update(0) > 0) {
+ float vals[3] = {0.0};
+ bool got_accel = false;
+
+ auto sensor_events = sm["sensorEvents"].getSensorEvents();
+ for (auto sensor_event : sensor_events) {
+ if (sensor_event.which() == cereal::SensorEventData::ACCELERATION) {
+ auto v = sensor_event.getAcceleration().getV();
+ if (v.size() < 3) {
+ continue; //wtf
}
- } else if (cmsg.type == -1) {
+ for (int j = 0; j < 3; j++) {
+ vals[j] = v[j];
+ }
+ got_accel = true;
break;
}
}
- zmq_msg_close(&msg);
-
- } else if (which == sensor_sock) {
- float vs[3] = {0.0};
- bool got_accel = acceleration_from_sensor_sock(sockraw, vs);
-
uint64_t ts = nanos_since_boot();
if (got_accel && ts - s->rear.last_sag_ts > 10000000) { // 10 ms
s->rear.last_sag_ts = ts;
- s->rear.last_sag_acc_z = -vs[2];
+ s->rear.last_sag_acc_z = -vals[2];
}
}
}
zpoller_destroy(&poller);
zsock_destroy(&cameraops);
- zsock_destroy(&sensor_sock);
zsock_destroy(&terminate);
return NULL;
diff --git a/selfdrive/camerad/cameras/camera_qcom.h b/selfdrive/camerad/cameras/camera_qcom.h
index bb9e513027..e2456c253a 100644
--- a/selfdrive/camerad/cameras/camera_qcom.h
+++ b/selfdrive/camerad/cameras/camera_qcom.h
@@ -1,9 +1,11 @@
-#ifndef CAMERA_H
-#define CAMERA_H
+#pragma once
#include
#include
#include
+#include
+#include
+#include "messaging.hpp"
#include "msmb_isp.h"
#include "msmb_ispif.h"
@@ -25,6 +27,18 @@
#define NUM_FOCUS 8
+#define LP3_AF_DAC_DOWN 366
+#define LP3_AF_DAC_UP 634
+#define LP3_AF_DAC_M 440
+#define LP3_AF_DAC_3SIG 52
+#define OP3T_AF_DAC_DOWN 224
+#define OP3T_AF_DAC_UP 456
+#define OP3T_AF_DAC_M 300
+#define OP3T_AF_DAC_3SIG 96
+
+#define FOCUS_RECOVER_PATIENCE 50 // 2.5 seconds of complete blur
+#define FOCUS_RECOVER_STEPS 240 // 6 seconds
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -48,7 +62,8 @@ typedef struct CameraState {
int device;
- void* ops_sock;
+ void* ops_sock_handle;
+ zsock_t * ops_sock;
uint32_t pixel_clock;
uint32_t line_length_pclk;
@@ -81,7 +96,7 @@ typedef struct CameraState {
int cur_frame_length;
int cur_integ_lines;
- float digital_gain;
+ std::atomic digital_gain;
StreamState ss[3];
@@ -98,7 +113,9 @@ typedef struct CameraState {
uint16_t cur_lens_pos;
uint64_t last_sag_ts;
float last_sag_acc_z;
- float lens_true_pos;
+ std::atomic lens_true_pos;
+
+ std::atomic self_recover; // af recovery counter, neg is patience, pos is active
int fps;
@@ -127,5 +144,3 @@ int sensor_write_regs(CameraState *s, struct msm_camera_i2c_reg_array* arr, size
#ifdef __cplusplus
} // extern "C"
#endif
-
-#endif
diff --git a/selfdrive/camerad/cameras/camera_qcom2.c b/selfdrive/camerad/cameras/camera_qcom2.c
index 035a95d103..3116a062bc 100644
--- a/selfdrive/camerad/cameras/camera_qcom2.c
+++ b/selfdrive/camerad/cameras/camera_qcom2.c
@@ -28,6 +28,7 @@
//#define FRAME_STRIDE 1936 // for 8 bit output
#define FRAME_STRIDE 2416 // for 10 bit output
+/*
static void hexdump(uint8_t *data, int len) {
for (int i = 0; i < len; i++) {
if (i!=0&&i%0x10==0) printf("\n");
@@ -35,6 +36,7 @@ static void hexdump(uint8_t *data, int len) {
}
printf("\n");
}
+*/
extern volatile sig_atomic_t do_exit;
@@ -80,8 +82,6 @@ int device_control(int fd, int op_code, int session_handle, int dev_handle) {
}
void *alloc_w_mmu_hdl(int video0_fd, int len, int align, int flags, uint32_t *handle, int mmu_hdl, int mmu_hdl2) {
- int ret;
-
struct cam_mem_mgr_alloc_cmd mem_mgr_alloc_cmd = {0};
mem_mgr_alloc_cmd.len = len;
mem_mgr_alloc_cmd.align = align;
@@ -141,7 +141,7 @@ void sensors_poke(struct CameraState *s, int request_id) {
pkt->header.size = size;
pkt->header.op_code = 0x7f;
pkt->header.request_id = request_id;
- struct cam_cmd_buf_desc *buf_desc = (struct cam_cmd_buf_desc *)&pkt->payload;
+ //struct cam_cmd_buf_desc *buf_desc = (struct cam_cmd_buf_desc *)&pkt->payload;
struct cam_config_dev_cmd config_dev_cmd = {};
config_dev_cmd.session_handle = s->session_handle;
@@ -170,7 +170,7 @@ void sensors_i2c(struct CameraState *s, struct i2c_random_wr_payload* dat, int l
buf_desc[0].size = buf_desc[0].length = sizeof(struct cam_cmd_i2c_random_wr) + (len-1)*sizeof(struct i2c_random_wr_payload);
buf_desc[0].type = CAM_CMD_BUF_I2C;
- struct cam_cmd_power *power = alloc(s->video0_fd, buf_desc[0].size, 8, CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, &buf_desc[0].mem_handle);
+ struct cam_cmd_power *power = alloc(s->video0_fd, buf_desc[0].size, 8, CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, (uint32_t*)&buf_desc[0].mem_handle);
struct cam_cmd_i2c_random_wr *i2c_random_wr = (void*)power;
i2c_random_wr->header.count = len;
i2c_random_wr->header.op_code = 1;
@@ -207,7 +207,7 @@ void sensors_init(int video0_fd, int sensor_fd, int camera_num) {
buf_desc[0].size = buf_desc[0].length = sizeof(struct cam_cmd_i2c_info) + sizeof(struct cam_cmd_probe);
buf_desc[0].type = CAM_CMD_BUF_LEGACY;
- struct cam_cmd_i2c_info *i2c_info = alloc(video0_fd, buf_desc[0].size, 8, CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, &buf_desc[0].mem_handle);
+ struct cam_cmd_i2c_info *i2c_info = alloc(video0_fd, buf_desc[0].size, 8, CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, (uint32_t*)&buf_desc[0].mem_handle);
struct cam_cmd_probe *probe = (struct cam_cmd_probe *)((uint8_t *)i2c_info) + sizeof(struct cam_cmd_i2c_info);
switch (camera_num) {
@@ -244,11 +244,11 @@ void sensors_init(int video0_fd, int sensor_fd, int camera_num) {
//buf_desc[1].size = buf_desc[1].length = 148;
buf_desc[1].size = buf_desc[1].length = 196;
buf_desc[1].type = CAM_CMD_BUF_I2C;
- struct cam_cmd_power *power = alloc(video0_fd, buf_desc[1].size, 8, CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, &buf_desc[1].mem_handle);
+ struct cam_cmd_power *power = alloc(video0_fd, buf_desc[1].size, 8, CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, (uint32_t*)&buf_desc[1].mem_handle);
memset(power, 0, buf_desc[1].size);
struct cam_cmd_unconditional_wait *unconditional_wait;
- void *ptr = power;
+ //void *ptr = power;
// 7750
/*power->count = 2;
power->cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_UP;
@@ -264,7 +264,7 @@ void sensors_init(int video0_fd, int sensor_fd, int camera_num) {
power->power_settings[2].power_seq_type = 2; // digital
power->power_settings[3].power_seq_type = 8; // reset low
power = (void*)power + (sizeof(struct cam_cmd_power) + (power->count-1)*sizeof(struct cam_power_settings));
-
+
unconditional_wait = (void*)power;
unconditional_wait->cmd_type = CAMERA_SENSOR_CMD_TYPE_WAIT;
unconditional_wait->delay = 5;
@@ -353,7 +353,7 @@ void sensors_init(int video0_fd, int sensor_fd, int camera_num) {
power = (void*)power + (sizeof(struct cam_cmd_power) + (power->count-1)*sizeof(struct cam_power_settings));
LOGD("probing the sensor");
- int ret = cam_control(sensor_fd, CAM_SENSOR_PROBE_CMD, (void *)cam_packet_handle, 0);
+ int ret = cam_control(sensor_fd, CAM_SENSOR_PROBE_CMD, (void *)(uintptr_t)cam_packet_handle, 0);
assert(ret == 0);
munmap(i2c_info, buf_desc[0].size);
@@ -407,8 +407,7 @@ void config_isp(struct CameraState *s, int io_mem_handle, int fence, int request
}
buf_desc[1].type = CAM_CMD_BUF_GENERIC;
buf_desc[1].meta_data = CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON;
- // printf("- ispc allocing 2 for sync_obj %d, req_id %d -\n", fence, request_id);
- uint32_t *buf2 = alloc(s->video0_fd, buf_desc[1].size, 0x20, CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, &buf_desc[1].mem_handle);
+ uint32_t *buf2 = alloc(s->video0_fd, buf_desc[1].size, 0x20, CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, (uint32_t*)&buf_desc[1].mem_handle);
// cam_isp_packet_generic_blob_handler
uint32_t tmp[] = {
@@ -431,7 +430,7 @@ void config_isp(struct CameraState *s, int io_mem_handle, int fence, int request
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
memcpy(buf2, tmp, sizeof(tmp));
if (io_mem_handle != 0) {
@@ -537,7 +536,6 @@ void enqueue_buffer(struct CameraState *s, int i) {
// ******************* camera *******************
static void camera_release_buffer(void* cookie, int i) {
- int ret;
CameraState *s = cookie;
enqueue_buffer(s, i);
}
@@ -629,7 +627,7 @@ static void camera_open(CameraState *s, VisionBuf* b) {
acquire_dev_cmd.handle_type = CAM_HANDLE_USER_POINTER;
acquire_dev_cmd.num_resources = 1;
acquire_dev_cmd.resource_hdl = (uint64_t)&isp_resource;
-
+
isp_resource.resource_id = CAM_ISP_RES_ID_PORT;
isp_resource.length = sizeof(struct cam_isp_in_port_info) + sizeof(struct cam_isp_out_port_info)*(1-1);
isp_resource.handle_type = CAM_HANDLE_USER_POINTER;
@@ -662,7 +660,7 @@ static void camera_open(CameraState *s, VisionBuf* b) {
in_port_info->test_pattern = 0x2; // 0x3?
in_port_info->usage_type = 0x0;
-
+
in_port_info->left_start = 0x0;
in_port_info->left_stop = FRAME_WIDTH - 1;
in_port_info->left_width = FRAME_WIDTH;
@@ -683,10 +681,10 @@ static void camera_open(CameraState *s, VisionBuf* b) {
in_port_info->num_out_res = 0x1;
in_port_info->data[0] = (struct cam_isp_out_port_info){
- .res_type = CAM_ISP_IFE_OUT_RES_RDI_0,
+ .res_type = CAM_ISP_IFE_OUT_RES_RDI_0,
//.format = CAM_FORMAT_MIPI_RAW_12,
.format = CAM_FORMAT_MIPI_RAW_10,
- .width = FRAME_WIDTH,
+ .width = FRAME_WIDTH,
.height = FRAME_HEIGHT,
.comp_grp_id = 0x0, .split_point = 0x0, .secure_mode = 0x0,
};
@@ -712,8 +710,7 @@ static void camera_open(CameraState *s, VisionBuf* b) {
// acquires done
// config ISP
- // 984480 = 3 * 65632 * (1+4) ?
- void *buf0 = alloc_w_mmu_hdl(s->video0_fd, 984480, 0x20, CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, &s->buf0_handle, s->device_iommu, s->cdm_iommu);
+ alloc_w_mmu_hdl(s->video0_fd, 984480, 0x20, CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, (uint32_t*)&s->buf0_handle, s->device_iommu, s->cdm_iommu);
config_isp(s, 0, 0, 1, s->buf0_handle, 0);
LOG("-- Configuring sensor");
@@ -736,7 +733,7 @@ static void camera_open(CameraState *s, VisionBuf* b) {
buf_desc[0].size = buf_desc[0].length = sizeof(struct cam_csiphy_info);
buf_desc[0].type = CAM_CMD_BUF_GENERIC;
- struct cam_csiphy_info *csiphy_info = alloc(s->video0_fd, buf_desc[0].size, 8, CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, &buf_desc[0].mem_handle);
+ struct cam_csiphy_info *csiphy_info = alloc(s->video0_fd, buf_desc[0].size, 8, CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, (uint32_t*)&buf_desc[0].mem_handle);
csiphy_info->lane_mask = 0x1f;
csiphy_info->lane_assign = 0x3210;// skip clk. How is this 16 bit for 5 channels??
@@ -840,7 +837,7 @@ void cameras_open(MultiCameraState *s, VisionBuf *camera_bufs_rear, VisionBuf *c
s->rear.device_iommu = s->front.device_iommu = s->wide.device_iommu = device_iommu;
s->rear.cdm_iommu = s->front.cdm_iommu = s->wide.cdm_iommu = cdm_iommu;
- // subscribe
+ // subscribe
LOG("-- Subscribing");
static struct v4l2_event_subscription sub = {0};
sub.type = 0x8000000;
diff --git a/selfdrive/camerad/cameras/camera_webcam.cc b/selfdrive/camerad/cameras/camera_webcam.cc
index da8ed5de3e..972d9643f4 100644
--- a/selfdrive/camerad/cameras/camera_webcam.cc
+++ b/selfdrive/camerad/cameras/camera_webcam.cc
@@ -222,7 +222,6 @@ CameraInfo cameras_supported[CAMERA_ID_MAX] = {
};
void cameras_init(MultiCameraState *s) {
- memset(s, 0, sizeof(*s));
camera_init(&s->rear, CAMERA_ID_LGC920, 20);
s->rear.transform = (mat3){{
diff --git a/selfdrive/camerad/cameras/sensor2_i2c.h b/selfdrive/camerad/cameras/sensor2_i2c.h
index 709d6497b8..0fbf63c09a 100644
--- a/selfdrive/camerad/cameras/sensor2_i2c.h
+++ b/selfdrive/camerad/cameras/sensor2_i2c.h
@@ -371,8 +371,8 @@ struct i2c_random_wr_payload init_array_ar0231[] = {
};
struct i2c_random_wr_payload poke_array_ov7750[] = {
- {0x3208, 0x0}, {0x380e, 0x1a}, {0x380f, 0xf0}, {0x3500, 0x0}, {0x3501, 0x0}, {0x3502, 0x10}, {0x350a, 0x0}, {0x350b, 0x10}, {0x3208, 0x10}, {0x3208, 0xa0},
- //{0x3208, 0x0}, {0x380e, 0x1a}, {0x380f, 0xf0}, {0x3500, 0x0}, {0x3501, 0x0}, {0x3502, 0x10}, {0x350a, 0x0}, {0x350b, 0x10}, {0x3208, 0x10}, {0x3208, 0xa0},
+ {0x3208, 0x0}, {0x380e, 0x1a}, {0x380f, 0xf0}, {0x3500, 0x0}, {0x3501, 0x0}, {0x3502, 0x10}, {0x350a, 0x0}, {0x350b, 0x10}, {0x3208, 0x10}, {0x3208, 0xa0},
+ //{0x3208, 0x0}, {0x380e, 0x1a}, {0x380f, 0xf0}, {0x3500, 0x0}, {0x3501, 0x0}, {0x3502, 0x10}, {0x350a, 0x0}, {0x350b, 0x10}, {0x3208, 0x10}, {0x3208, 0xa0},
};
struct i2c_random_wr_payload preinit_array_ov7750[] = {
diff --git a/selfdrive/camerad/imgproc/conv.cl b/selfdrive/camerad/imgproc/conv.cl
index f92d356705..a7115ae76c 100644
--- a/selfdrive/camerad/imgproc/conv.cl
+++ b/selfdrive/camerad/imgproc/conv.cl
@@ -3,7 +3,7 @@
// convert input rgb image to single channel then conv
__kernel void rgb2gray_conv2d(
- const __global uchar * input,
+ const __global uchar * input,
__global short * output,
__constant short * filter,
__local uchar3 * cached
@@ -23,8 +23,8 @@ __kernel void rgb2gray_conv2d(
// pad
if (
- get_global_id(0) < HALF_FILTER_SIZE ||
- get_global_id(0) > IMAGE_W - HALF_FILTER_SIZE - 1 ||
+ get_global_id(0) < HALF_FILTER_SIZE ||
+ get_global_id(0) > IMAGE_W - HALF_FILTER_SIZE - 1 ||
get_global_id(1) < HALF_FILTER_SIZE ||
get_global_id(1) > IMAGE_H - HALF_FILTER_SIZE - 1
)
@@ -32,11 +32,11 @@ __kernel void rgb2gray_conv2d(
barrier(CLK_LOCAL_MEM_FENCE);
return;
}
- else
+ else
{
int localColOffset = -1;
int globalColOffset = -1;
-
+
// cache extra
if ( get_local_id(0) < HALF_FILTER_SIZE )
{
@@ -51,7 +51,7 @@ __kernel void rgb2gray_conv2d(
{
localColOffset = get_local_id(0) + TWICE_HALF_FILTER_SIZE;
globalColOffset = HALF_FILTER_SIZE;
-
+
cached[ myLocal + HALF_FILTER_SIZE ].x = input[ my * 3 + HALF_FILTER_SIZE * 3 ];
cached[ myLocal + HALF_FILTER_SIZE ].y = input[ my * 3 + HALF_FILTER_SIZE * 3 + 1];
cached[ myLocal + HALF_FILTER_SIZE ].z = input[ my * 3 + HALF_FILTER_SIZE * 3 + 2];
diff --git a/selfdrive/camerad/imgproc/pool.cl b/selfdrive/camerad/imgproc/pool.cl
index 3ba86ae24e..d674b5f363 100644
--- a/selfdrive/camerad/imgproc/pool.cl
+++ b/selfdrive/camerad/imgproc/pool.cl
@@ -1,6 +1,6 @@
// calculate variance in each subregion
__kernel void var_pool(
- const __global char * input,
+ const __global char * input,
__global ushort * output // should not be larger than 128*128 so uint16
)
{
@@ -11,7 +11,7 @@ __kernel void var_pool(
float fsum = 0;
char mean, max;
-
+
for (int i = 0; i < size; i++) {
int x_offset = i % X_PITCH;
int y_offset = i / X_PITCH;
diff --git a/selfdrive/camerad/imgproc/utils.h b/selfdrive/camerad/imgproc/utils.h
index f77a456912..203ac57a66 100644
--- a/selfdrive/camerad/imgproc/utils.h
+++ b/selfdrive/camerad/imgproc/utils.h
@@ -11,8 +11,8 @@
#define ROI_Y_MIN 2
#define ROI_Y_MAX 3
-#define LM_THRESH 222
-#define LM_PREC_THRESH 0.9
+#define LM_THRESH 120
+#define LM_PREC_THRESH 0.9 // 90 perc is blur
// only apply to QCOM
#define FULL_STRIDE_X 1280
@@ -27,4 +27,4 @@ const int16_t lapl_conv_krnl[9] = {0, 1, 0,
void get_lapmap_one(int16_t *lap, uint16_t *res, int x_pitch, int y_pitch);
bool is_blur(uint16_t *lapmap);
-#endif
\ No newline at end of file
+#endif
diff --git a/selfdrive/camerad/main.cc b/selfdrive/camerad/main.cc
index 3e9652afcf..d43578121f 100644
--- a/selfdrive/camerad/main.cc
+++ b/selfdrive/camerad/main.cc
@@ -2,7 +2,7 @@
#include
#include
-#ifdef QCOM
+#if defined(QCOM) && !defined(QCOM_REPLAY)
#include "cameras/camera_qcom.h"
#elif QCOM2
#include "cameras/camera_qcom2.h"
@@ -15,6 +15,7 @@
#include "common/util.h"
#include "common/swaglog.h"
+#include "common/ipc.h"
#include "common/visionipc.h"
#include "common/visionbuf.h"
#include "common/visionimg.h"
@@ -29,9 +30,7 @@
#include
#include
-#include
#include
-#include "cereal/gen/cpp/log.capnp.h"
#define UI_BUF_COUNT 4
#define DEBAYER_LOCAL_WORKSIZE 16
@@ -168,11 +167,7 @@ struct VisionState {
zsock_t *terminate_pub;
- Context * msg_context;
- PubSocket *frame_sock;
- PubSocket *front_frame_sock;
- PubSocket *wide_frame_sock;
- PubSocket *thumbnail_sock;
+ PubMaster *pm;
pthread_mutex_t clients_lock;
VisionClientState clients[MAX_CLIENTS];
@@ -184,16 +179,9 @@ void* frontview_thread(void *arg) {
VisionState *s = (VisionState*)arg;
set_thread_name("frontview");
-
- s->msg_context = Context::create();
-
// we subscribe to this for placement of the AE metering box
// TODO: the loop is bad, ideally models shouldn't affect sensors
- Context *msg_context = Context::create();
- SubSocket *monitoring_sock = SubSocket::create(msg_context, "driverState", "127.0.0.1", true);
- SubSocket *dmonstate_sock = SubSocket::create(msg_context, "dMonitoringState", "127.0.0.1", true);
- assert(monitoring_sock != NULL);
- assert(dmonstate_sock != NULL);
+ SubMaster sm({"driverState", "dMonitoringState"});
cl_command_queue q = clCreateCommandQueue(s->context, s->device_id, 0, &err);
assert(err == 0);
@@ -208,7 +196,7 @@ void* frontview_thread(void *arg) {
int rgb_idx = ui_idx;
FrameMetadata frame_data = s->cameras.front.camera_bufs_metadata[buf_idx];
- double t1 = millis_since_boot();
+ //double t1 = millis_since_boot();
cl_event debayer_event;
if (s->cameras.front.ci.bayer) {
@@ -243,21 +231,12 @@ void* frontview_thread(void *arg) {
tbuffer_release(&s->cameras.front.camera_tb, buf_idx);
visionbuf_sync(&s->rgb_front_bufs[ui_idx], VISIONBUF_SYNC_FROM_DEVICE);
+ sm.update(0);
// no more check after gps check
- if (!s->rhd_front_checked) {
- Message *msg_dmon = dmonstate_sock->receive(true);
- if (msg_dmon != NULL) {
- auto amsg = kj::heapArray((msg_dmon->getSize() / sizeof(capnp::word)) + 1);
- memcpy(amsg.begin(), msg_dmon->getData(), msg_dmon->getSize());
-
- capnp::FlatArrayMessageReader cmsg(amsg);
- cereal::Event::Reader event = cmsg.getRoot();
-
- s->rhd_front = event.getDMonitoringState().getIsRHD();
- s->rhd_front_checked = event.getDMonitoringState().getRhdChecked();
-
- delete msg_dmon;
- }
+ if (!s->rhd_front_checked && sm.updated("dMonitoringState")) {
+ auto state = sm["dMonitoringState"].getDMonitoringState();
+ s->rhd_front = state.getIsRHD();
+ s->rhd_front_checked = state.getRhdChecked();
}
#ifdef NOSCREEN
@@ -266,37 +245,26 @@ void* frontview_thread(void *arg) {
}
#endif
- Message *msg = monitoring_sock->receive(true);
- if (msg != NULL) {
- auto amsg = kj::heapArray((msg->getSize() / sizeof(capnp::word)) + 1);
- memcpy(amsg.begin(), msg->getData(), msg->getSize());
-
- capnp::FlatArrayMessageReader cmsg(amsg);
- cereal::Event::Reader event = cmsg.getRoot();
-
- float face_prob = event.getDriverState().getFaceProb();
+ if (sm.updated("driverState")) {
+ auto state = sm["driverState"].getDriverState();
+ float face_prob = state.getFaceProb();
float face_position[2];
- face_position[0] = event.getDriverState().getFacePosition()[0];
- face_position[1] = event.getDriverState().getFacePosition()[1];
+ face_position[0] = state.getFacePosition()[0];
+ face_position[1] = state.getFacePosition()[1];
// set front camera metering target
- if (face_prob > 0.4)
- {
+ if (face_prob > 0.4) {
int x_offset = s->rhd_front ? 0:s->rgb_front_width - 0.5 * s->rgb_front_height;
s->front_meteringbox_xmin = x_offset + (face_position[0] + 0.5) * (0.5 * s->rgb_front_height) - 72;
s->front_meteringbox_xmax = x_offset + (face_position[0] + 0.5) * (0.5 * s->rgb_front_height) + 72;
s->front_meteringbox_ymin = (face_position[1] + 0.5) * (s->rgb_front_height) - 72;
s->front_meteringbox_ymax = (face_position[1] + 0.5) * (s->rgb_front_height) + 72;
- }
- else // use default setting if no face
- {
+ } else {// use default setting if no face
s->front_meteringbox_ymin = s->rgb_front_height * 1 / 3;
s->front_meteringbox_ymax = s->rgb_front_height * 1;
s->front_meteringbox_xmin = s->rhd_front ? 0:s->rgb_front_width * 3 / 5;
s->front_meteringbox_xmax = s->rhd_front ? s->rgb_front_width * 2 / 5:s->rgb_front_width;
}
-
- delete msg;
}
// auto exposure
@@ -373,7 +341,7 @@ void* frontview_thread(void *arg) {
// send frame event
{
- if (s->front_frame_sock != NULL) {
+ if (s->pm != NULL) {
capnp::MallocMessageBuilder msg;
cereal::Event::Builder event = msg.initRoot();
event.setLogMonoTime(nanos_since_boot());
@@ -392,9 +360,7 @@ void* frontview_thread(void *arg) {
framed.setGainFrac(frame_data.gain_frac);
framed.setFrameType(cereal::FrameData::FrameType::FRONT);
- auto words = capnp::messageToFlatArray(msg);
- auto bytes = words.asBytes();
- s->front_frame_sock->send((char*)bytes.begin(), bytes.size());
+ s->pm->send("frontFrame", msg);
}
}
@@ -405,13 +371,10 @@ void* frontview_thread(void *arg) {
tbuffer_dispatch(&s->ui_front_tb, ui_idx);
- double t2 = millis_since_boot();
-
+ //double t2 = millis_since_boot();
//LOGD("front process: %.2fms", t2-t1);
}
-
- delete monitoring_sock;
- delete dmonstate_sock;
+ clReleaseCommandQueue(q);
return NULL;
}
@@ -590,12 +553,21 @@ void* processing_thread(void *arg) {
set_thread_name("processing");
- err = set_realtime_priority(1);
+ err = set_realtime_priority(51);
LOG("setpriority returns %d", err);
+#if defined(QCOM) && !defined(QCOM_REPLAY)
+ std::unique_ptr rgb_roi_buf = std::make_unique((s->rgb_width/NUM_SEGMENTS_X)*(s->rgb_height/NUM_SEGMENTS_Y)*3);
+ std::unique_ptr conv_result = std::make_unique((s->rgb_width/NUM_SEGMENTS_X)*(s->rgb_height/NUM_SEGMENTS_Y));
+#endif
+
// init cl stuff
+#ifdef __APPLE__
+ cl_command_queue q = clCreateCommandQueue(s->context, s->device_id, 0, &err);
+#else
const cl_queue_properties props[] = {0}; //CL_QUEUE_PRIORITY_KHR, CL_QUEUE_PRIORITY_HIGH_KHR, 0};
cl_command_queue q = clCreateCommandQueueWithProperties(s->context, s->device_id, props, &err);
+#endif
assert(err == 0);
// init the net
@@ -660,13 +632,14 @@ void* processing_thread(void *arg) {
visionbuf_sync(&s->rgb_bufs[rgb_idx], VISIONBUF_SYNC_FROM_DEVICE);
+<<<<<<< HEAD
#ifdef NOSCREEN
if (frame_data.frame_id % 4 == 1) {
sendrgb(&s->cameras, (uint8_t*) s->rgb_bufs[rgb_idx].addr, s->rgb_bufs[rgb_idx].len, 0);
}
#endif
-#ifdef QCOM
+#if defined(QCOM) && !defined(QCOM_REPLAY)
/*FILE *dump_rgb_file = fopen("/tmp/process_dump.rgb", "wb");
fwrite(s->rgb_bufs[rgb_idx].addr, s->rgb_bufs[rgb_idx].len, sizeof(uint8_t), dump_rgb_file);
fclose(dump_rgb_file);
@@ -675,13 +648,12 @@ void* processing_thread(void *arg) {
/*double t10 = millis_since_boot();*/
// cache rgb roi and write to cl
- uint8_t *rgb_roi_buf = new uint8_t[(s->rgb_width/NUM_SEGMENTS_X)*(s->rgb_height/NUM_SEGMENTS_Y)*3];
int roi_id = cnt % ((ROI_X_MAX-ROI_X_MIN+1)*(ROI_Y_MAX-ROI_Y_MIN+1)); // rolling roi
int roi_x_offset = roi_id % (ROI_X_MAX-ROI_X_MIN+1);
int roi_y_offset = roi_id / (ROI_X_MAX-ROI_X_MIN+1);
for (int r=0;r<(s->rgb_height/NUM_SEGMENTS_Y);r++) {
- memcpy(rgb_roi_buf + r * (s->rgb_width/NUM_SEGMENTS_X) * 3,
+ memcpy(rgb_roi_buf.get() + r * (s->rgb_width/NUM_SEGMENTS_X) * 3,
(uint8_t *) s->rgb_bufs[rgb_idx].addr + \
(ROI_Y_MIN + roi_y_offset) * s->rgb_height/NUM_SEGMENTS_Y * FULL_STRIDE_X * 3 + \
(ROI_X_MIN + roi_x_offset) * s->rgb_width/NUM_SEGMENTS_X * 3 + r * FULL_STRIDE_X * 3,
@@ -689,7 +661,7 @@ void* processing_thread(void *arg) {
}
err = clEnqueueWriteBuffer (q, s->rgb_conv_roi_cl, true, 0,
- s->rgb_width/NUM_SEGMENTS_X * s->rgb_height/NUM_SEGMENTS_Y * 3 * sizeof(uint8_t), rgb_roi_buf, 0, 0, 0);
+ s->rgb_width/NUM_SEGMENTS_X * s->rgb_height/NUM_SEGMENTS_Y * 3 * sizeof(uint8_t), rgb_roi_buf.get(), 0, 0, 0);
assert(err == 0);
/*double t11 = millis_since_boot();
@@ -712,32 +684,57 @@ void* processing_thread(void *arg) {
clWaitForEvents(1, &conv_event);
clReleaseEvent(conv_event);
- int16_t *conv_result = new int16_t[(s->rgb_width/NUM_SEGMENTS_X)*(s->rgb_height/NUM_SEGMENTS_Y)];
err = clEnqueueReadBuffer(q, s->rgb_conv_result_cl, true, 0,
- s->rgb_width/NUM_SEGMENTS_X * s->rgb_height/NUM_SEGMENTS_Y * sizeof(int16_t), conv_result, 0, 0, 0);
+ s->rgb_width/NUM_SEGMENTS_X * s->rgb_height/NUM_SEGMENTS_Y * sizeof(int16_t), conv_result.get(), 0, 0, 0);
assert(err == 0);
/*t11 = millis_since_boot();
printf("conv time: %f ms\n", t11 - t10);
t10 = millis_since_boot();*/
- get_lapmap_one(conv_result, &s->lapres[roi_id], s->rgb_width/NUM_SEGMENTS_X, s->rgb_height/NUM_SEGMENTS_Y);
+ get_lapmap_one(conv_result.get(), &s->lapres[roi_id], s->rgb_width/NUM_SEGMENTS_X, s->rgb_height/NUM_SEGMENTS_Y);
/*t11 = millis_since_boot();
printf("pool time: %f ms\n", t11 - t10);
t10 = millis_since_boot();*/
- delete [] rgb_roi_buf;
- delete [] conv_result;
-
/*t11 = millis_since_boot();
printf("process time: %f ms\n ----- \n", t11 - t10);
t10 = millis_since_boot();*/
+
+ // setup self recover
+ const float lens_true_pos = s->cameras.rear.lens_true_pos;
+ if (is_blur(&s->lapres[0]) &&
+ (lens_true_pos < (s->cameras.device == DEVICE_LP3? LP3_AF_DAC_DOWN:OP3T_AF_DAC_DOWN)+1 ||
+ lens_true_pos > (s->cameras.device == DEVICE_LP3? LP3_AF_DAC_UP:OP3T_AF_DAC_UP)-1) &&
+ s->cameras.rear.self_recover < 2) {
+ // truly stuck, needs help
+ s->cameras.rear.self_recover -= 1;
+ if (s->cameras.rear.self_recover < -FOCUS_RECOVER_PATIENCE) {
+ LOGW("rear camera bad state detected. attempting recovery from %.1f, recover state is %d",
+ lens_true_pos, s->cameras.rear.self_recover.load());
+ s->cameras.rear.self_recover = FOCUS_RECOVER_STEPS + ((lens_true_pos < (s->cameras.device == DEVICE_LP3? LP3_AF_DAC_M:OP3T_AF_DAC_M))?1:0); // parity determined by which end is stuck at
+ }
+ } else if ((lens_true_pos < (s->cameras.device == DEVICE_LP3? LP3_AF_DAC_M - LP3_AF_DAC_3SIG:OP3T_AF_DAC_M - OP3T_AF_DAC_3SIG) ||
+ lens_true_pos > (s->cameras.device == DEVICE_LP3? LP3_AF_DAC_M + LP3_AF_DAC_3SIG:OP3T_AF_DAC_M + OP3T_AF_DAC_3SIG)) &&
+ s->cameras.rear.self_recover < 2) {
+ // in suboptimal position with high prob, but may still recover by itself
+ s->cameras.rear.self_recover -= 1;
+ if (s->cameras.rear.self_recover < -(FOCUS_RECOVER_PATIENCE*3)) {
+ LOGW("rear camera bad state detected. attempting recovery from %.1f, recover state is %d", lens_true_pos, s->cameras.rear.self_recover.load());
+ s->cameras.rear.self_recover = FOCUS_RECOVER_STEPS/2 + ((lens_true_pos < (s->cameras.device == DEVICE_LP3? LP3_AF_DAC_M:OP3T_AF_DAC_M))?1:0);
+ }
+ } else if (s->cameras.rear.self_recover < 0) {
+ s->cameras.rear.self_recover += 1; // reset if fine
+ }
+
#endif
double t2 = millis_since_boot();
+#ifndef QCOM2
uint8_t *bgr_ptr = (uint8_t*)s->rgb_bufs[rgb_idx].addr;
+#endif
double yt1 = millis_since_boot();
@@ -746,8 +743,6 @@ void* processing_thread(void *arg) {
s->yuv_metas[yuv_idx] = frame_data;
uint8_t* yuv_ptr_y = s->yuv_bufs[yuv_idx].y;
- uint8_t* yuv_ptr_u = s->yuv_bufs[yuv_idx].u;
- uint8_t* yuv_ptr_v = s->yuv_bufs[yuv_idx].v;
cl_mem yuv_cl = s->yuv_cl[yuv_idx];
rgb_to_yuv_queue(&s->rgb_to_yuv_state, q, s->rgb_bufs_cl[rgb_idx], yuv_cl);
visionbuf_sync(&s->yuv_ion[yuv_idx], VISIONBUF_SYNC_FROM_DEVICE);
@@ -760,7 +755,7 @@ void* processing_thread(void *arg) {
// send frame event
{
- if (s->frame_sock != NULL) {
+ if (s->pm != NULL) {
capnp::MallocMessageBuilder msg;
cereal::Event::Builder event = msg.initRoot();
event.setLogMonoTime(nanos_since_boot());
@@ -778,13 +773,14 @@ void* processing_thread(void *arg) {
framed.setLensTruePos(frame_data.lens_true_pos);
framed.setGainFrac(frame_data.gain_frac);
-#ifdef QCOM
+#if defined(QCOM) && !defined(QCOM_REPLAY)
kj::ArrayPtr focus_vals(&s->cameras.rear.focus[0], NUM_FOCUS);
kj::ArrayPtr focus_confs(&s->cameras.rear.confidence[0], NUM_FOCUS);
framed.setFocusVal(focus_vals);
framed.setFocusConf(focus_confs);
kj::ArrayPtr sharpness_score(&s->lapres[0], (ROI_X_MAX-ROI_X_MIN+1)*(ROI_Y_MAX-ROI_Y_MIN+1));
framed.setSharpnessScore(sharpness_score);
+ framed.setRecoverState(s->cameras.rear.self_recover);
#endif
// TODO: add this back
@@ -796,9 +792,7 @@ void* processing_thread(void *arg) {
kj::ArrayPtr transform_vs(&s->yuv_transform.v[0], 9);
framed.setTransform(transform_vs);
- auto words = capnp::messageToFlatArray(msg);
- auto bytes = words.asBytes();
- s->frame_sock->send((char*)bytes.begin(), bytes.size());
+ s->pm->send("frame", msg);
}
}
@@ -807,7 +801,7 @@ void* processing_thread(void *arg) {
// one thumbnail per 5 seconds (instead of %5 == 0 posenet)
if (cnt % 100 == 3) {
uint8_t* thumbnail_buffer = NULL;
- uint64_t thumbnail_len = 0;
+ unsigned long thumbnail_len = 0;
unsigned char *row = (unsigned char *)malloc(s->rgb_width/4*3);
@@ -859,10 +853,8 @@ void* processing_thread(void *arg) {
thumbnaild.setTimestampEof(frame_data.timestamp_eof);
thumbnaild.setThumbnail(kj::arrayPtr((const uint8_t*)thumbnail_buffer, thumbnail_len));
- auto words = capnp::messageToFlatArray(msg);
- auto bytes = words.asBytes();
- if (s->thumbnail_sock != NULL) {
- s->thumbnail_sock->send((char*)bytes.begin(), bytes.size());
+ if (s->pm != NULL) {
+ s->pm->send("thumbnail", msg);
}
free(thumbnail_buffer);
@@ -906,6 +898,7 @@ void* processing_thread(void *arg) {
LOGD("queued: %.2fms, yuv: %.2f, | processing: %.3fms", (t2-t1), (yt2-yt1), (t5-t1));
}
+ clReleaseCommandQueue(q);
return NULL;
}
@@ -1151,21 +1144,7 @@ void* visionserver_thread(void* arg) {
assert(terminate);
void* terminate_raw = zsock_resolve(terminate);
- unlink(VIPC_SOCKET_PATH);
-
- int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
- struct sockaddr_un addr = {
- .sun_family = AF_UNIX,
- .sun_path = VIPC_SOCKET_PATH,
- };
- err = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
- assert(err == 0);
-
- err = listen(sock, 3);
- assert(err == 0);
-
- // printf("waiting\n");
-
+ int sock = ipc_bind(VIPC_SOCKET_PATH);
while (!do_exit) {
zmq_pollitem_t polls[2] = {{0}};
polls[0].socket = terminate_raw;
@@ -1293,19 +1272,7 @@ cl_program build_pool_program(VisionState *s,
void cl_init(VisionState *s) {
int err;
- cl_platform_id platform_id = NULL;
- cl_uint num_devices;
- cl_uint num_platforms;
-
- err = clGetPlatformIDs(1, &platform_id, &num_platforms);
- assert(err == 0);
- err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1,
- &s->device_id, &num_devices);
- assert(err == 0);
-
- cl_print_info(platform_id, s->device_id);
- printf("\n");
-
+ s->device_id = cl_get_device_id(CL_DEVICE_TYPE_DEFAULT);
s->context = clCreateContext(NULL, 1, &s->device_id, NULL, NULL, &err);
assert(err == 0);
}
@@ -1385,6 +1352,7 @@ void init_buffers(VisionState *s) {
s->rgb_wide_width = s->cameras.wide.ci.frame_width;
s->rgb_wide_height = s->cameras.wide.ci.frame_height;
#endif
+
for (int i=0; irgb_front_width, s->rgb_front_height, &s->rgb_front_bufs[i]);
s->rgb_front_bufs_cl[i] = visionbuf_to_cl(&s->rgb_front_bufs[i], s->device_id, s->context);
@@ -1496,13 +1464,14 @@ void init_buffers(VisionState *s) {
s->debayer_cl_localWorkSize[1] = DEBAYER_LOCAL_WORKSIZE;
#ifdef QCOM
- s->prg_rgb_laplacian = build_conv_program(s, s->rgb_width/NUM_SEGMENTS_X, s->rgb_height/NUM_SEGMENTS_Y,
+ s->prg_rgb_laplacian = build_conv_program(s, s->rgb_width/NUM_SEGMENTS_X, s->rgb_height/NUM_SEGMENTS_Y,
3);
s->krnl_rgb_laplacian = clCreateKernel(s->prg_rgb_laplacian, "rgb2gray_conv2d", &err);
assert(err == 0);
- s->rgb_conv_roi_cl = clCreateBuffer(s->context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER,
+ // TODO: Removed CL_MEM_SVM_FINE_GRAIN_BUFFER, confirm it doesn't matter
+ s->rgb_conv_roi_cl = clCreateBuffer(s->context, CL_MEM_READ_WRITE,
s->rgb_width/NUM_SEGMENTS_X * s->rgb_height/NUM_SEGMENTS_Y * 3 * sizeof(uint8_t), NULL, NULL);
- s->rgb_conv_result_cl = clCreateBuffer(s->context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER,
+ s->rgb_conv_result_cl = clCreateBuffer(s->context, CL_MEM_READ_WRITE,
s->rgb_width/NUM_SEGMENTS_X * s->rgb_height/NUM_SEGMENTS_Y * sizeof(int16_t), NULL, NULL);
s->rgb_conv_filter_cl = clCreateBuffer(s->context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
9 * sizeof(int16_t), (void*)&lapl_conv_krnl, NULL);
@@ -1543,9 +1512,6 @@ void free_buffers(VisionState *s) {
#endif
for (int i=0; irgb_bufs[i]);
- }
-
- for (int i=0; irgb_front_bufs[i]);
}
#ifdef QCOM2
@@ -1555,7 +1521,21 @@ void free_buffers(VisionState *s) {
#endif
for (int i=0; iyuv_ion[i]);
+ visionbuf_free(&s->yuv_front_ion[i]);
}
+
+ clReleaseMemObject(s->rgb_conv_roi_cl);
+ clReleaseMemObject(s->rgb_conv_result_cl);
+ clReleaseMemObject(s->rgb_conv_filter_cl);
+
+ clReleaseProgram(s->prg_debayer_rear);
+ clReleaseProgram(s->prg_debayer_front);
+ clReleaseKernel(s->krnl_debayer_rear);
+ clReleaseKernel(s->krnl_debayer_front);
+
+ clReleaseProgram(s->prg_rgb_laplacian);
+ clReleaseKernel(s->krnl_rgb_laplacian);
+
}
void party(VisionState *s) {
@@ -1574,10 +1554,12 @@ void party(VisionState *s) {
processing_thread, s);
assert(err == 0);
+#if !defined(__APPLE__)
pthread_t frontview_thread_handle;
err = pthread_create(&frontview_thread_handle, NULL,
frontview_thread, s);
assert(err == 0);
+#endif
#ifdef QCOM2
pthread_t wideview_thread_handle;
err = pthread_create(&wideview_thread_handle, NULL,
@@ -1586,7 +1568,7 @@ void party(VisionState *s) {
#endif
// priority for cameras
- err = set_realtime_priority(1);
+ err = set_realtime_priority(51);
LOG("setpriority returns %d", err);
cameras_run(&s->cameras);
@@ -1602,9 +1584,11 @@ void party(VisionState *s) {
zsock_signal(s->terminate_pub, 0);
+#if (defined(QCOM) && !defined(QCOM_REPLAY)) || defined(WEBCAM) || defined(QCOM2)
LOG("joining frontview_thread");
err = pthread_join(frontview_thread_handle, NULL);
assert(err == 0);
+#endif
#ifdef QCOM2
LOG("joining wideview_thread");
err = pthread_join(wideview_thread_handle, NULL);
@@ -1622,14 +1606,13 @@ void party(VisionState *s) {
}
int main(int argc, char *argv[]) {
- int err;
- set_realtime_priority(1);
+ set_realtime_priority(51);
zsys_handler_set(NULL);
signal(SIGINT, (sighandler_t)set_do_exit);
signal(SIGTERM, (sighandler_t)set_do_exit);
- VisionState state = {0};
+ VisionState state = {};
VisionState *s = &state;
clu_init();
@@ -1644,16 +1627,8 @@ int main(int argc, char *argv[]) {
init_buffers(s);
-#if defined(QCOM) || defined(QCOM2)
- s->msg_context = Context::create();
- s->frame_sock = PubSocket::create(s->msg_context, "frame");
- s->front_frame_sock = PubSocket::create(s->msg_context, "frontFrame");
- s->wide_frame_sock = PubSocket::create(s->msg_context, "wideFrame");
- s->thumbnail_sock = PubSocket::create(s->msg_context, "thumbnail");
- assert(s->frame_sock != NULL);
- assert(s->front_frame_sock != NULL);
- assert(s->wide_frame_sock != NULL);
- assert(s->thumbnail_sock != NULL);
+#if (defined(QCOM) && !defined(QCOM_REPLAY)) || defined(QCOM2)
+ s->pm = new PubMaster({"frame", "frontFrame", "wideFrame", "thumbnail"});
#endif
#ifndef QCOM2
@@ -1664,13 +1639,9 @@ int main(int argc, char *argv[]) {
party(s);
-#if defined(QCOM) || defined(QCOM2)
- delete s->frame_sock;
- delete s->front_frame_sock;
- delete s->wide_frame_sock;
- delete s->thumbnail_sock;
- delete s->msg_context;
-#endif
+ if (s->pm != NULL) {
+ delete s->pm;
+ }
free_buffers(s);
cl_free(s);
diff --git a/selfdrive/camerad/snapshot/snapshot.py b/selfdrive/camerad/snapshot/snapshot.py
index 4ba10bf4be..317618c0b2 100755
--- a/selfdrive/camerad/snapshot/snapshot.py
+++ b/selfdrive/camerad/snapshot/snapshot.py
@@ -1,6 +1,5 @@
#!/usr/bin/env python3
import os
-import json
import signal
import subprocess
import time
@@ -8,9 +7,7 @@ from PIL import Image
from common.basedir import BASEDIR
from common.params import Params
from selfdrive.camerad.snapshot.visionipc import VisionIPC
-
-with open(BASEDIR + "/selfdrive/controls/lib/alerts_offroad.json") as json_file:
- OFFROAD_ALERTS = json.load(json_file)
+from selfdrive.controls.lib.alertmanager import set_offroad_alert
def jpeg_write(fn, dat):
@@ -26,7 +23,7 @@ def snapshot():
return None
params.put("IsTakingSnapshot", "1")
- params.put("Offroad_IsTakingSnapshot", json.dumps(OFFROAD_ALERTS["Offroad_IsTakingSnapshot"]))
+ set_offroad_alert("Offroad_IsTakingSnapshot", True)
time.sleep(2.0) # Give thermald time to read the param, or if just started give camerad time to start
# Check if camerad is already started
@@ -64,7 +61,7 @@ def snapshot():
proc.communicate()
params.put("IsTakingSnapshot", "0")
- params.delete("Offroad_IsTakingSnapshot")
+ set_offroad_alert("Offroad_IsTakingSnapshot", False)
return ret
diff --git a/selfdrive/camerad/snapshot/visionipc.py b/selfdrive/camerad/snapshot/visionipc.py
index 816db41208..4df79e2cc2 100644
--- a/selfdrive/camerad/snapshot/visionipc.py
+++ b/selfdrive/camerad/snapshot/visionipc.py
@@ -90,4 +90,4 @@ class VisionIPC():
buf = self.clib.visionstream_get(self.s, ffi.NULL)
pbuf = ffi.buffer(buf.addr, buf.len)
ret = np.frombuffer(pbuf, dtype=np.uint8).reshape((-1, self.buf_info.stride//3, 3))
- return ret[:self.buf_info.height, :self.buf_info.width, [2,1,0]]
+ return ret[:self.buf_info.height, :self.buf_info.width, [2, 1, 0]]
diff --git a/selfdrive/camerad/test/camera/test.c b/selfdrive/camerad/test/camera/test.c
index dc9b92ef13..4ff6a07526 100644
--- a/selfdrive/camerad/test/camera/test.c
+++ b/selfdrive/camerad/test/camera/test.c
@@ -35,7 +35,7 @@ void tbuffer_stop(TBuffer *tb) {
}
int main() {
- MultiCameraState s;
+ MultiCameraState s={};
cameras_init(&s);
VisionBuf camera_bufs_rear[0x10] = {0};
VisionBuf camera_bufs_focus[0x10] = {0};
diff --git a/selfdrive/camerad/test/frame_test.py b/selfdrive/camerad/test/frame_test.py
index 2518e80344..36e6733654 100755
--- a/selfdrive/camerad/test/frame_test.py
+++ b/selfdrive/camerad/test/frame_test.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python3
-import time
import numpy as np
import cereal.messaging as messaging
from PIL import ImageFont, ImageDraw, Image
@@ -7,13 +6,13 @@ from PIL import ImageFont, ImageDraw, Image
font = ImageFont.truetype("arial", size=72)
def get_frame(idx):
img = np.zeros((874, 1164, 3), np.uint8)
- img[100:400, 100:100+(idx%10)*100] = 255
+ img[100:400, 100:100+(idx % 10) * 100] = 255
# big number
- im2 = Image.new("RGB", (200,200))
+ im2 = Image.new("RGB", (200, 200))
draw = ImageDraw.Draw(im2)
draw.text((10, 100), "%02d" % idx, font=font)
- img[400:600, 400:600] = np.array(im2.getdata()).reshape((200,200,3))
+ img[400:600, 400:600] = np.array(im2.getdata()).reshape((200, 200, 3))
return img.tostring()
if __name__ == "__main__":
@@ -29,11 +28,10 @@ if __name__ == "__main__":
dat.valid = True
dat.frame = {
"frameId": idx,
- "image": frm[idx%len(frm)],
+ "image": frm[idx % len(frm)],
}
pm.send('frame', dat)
idx += 1
rk.keep_time()
#time.sleep(1.0)
-
diff --git a/selfdrive/camerad/test/yuv_bench/cnv.py b/selfdrive/camerad/test/yuv_bench/cnv.py
index 86fd0c9982..24fde0875a 100644
--- a/selfdrive/camerad/test/yuv_bench/cnv.py
+++ b/selfdrive/camerad/test/yuv_bench/cnv.py
@@ -1,5 +1,5 @@
import numpy as np
-import cv2
+import cv2 # pylint: disable=import-error
# img_bgr = np.zeros((874, 1164, 3), dtype=np.uint8)
# for y in range(874):
diff --git a/selfdrive/camerad/test/yuv_bench/yuv_bench.cc b/selfdrive/camerad/test/yuv_bench/yuv_bench.cc
index 22e71c4128..62860ea7cc 100644
--- a/selfdrive/camerad/test/yuv_bench/yuv_bench.cc
+++ b/selfdrive/camerad/test/yuv_bench/yuv_bench.cc
@@ -38,27 +38,8 @@ int main() {
// init cl
- /* Get Platform and Device Info */
- cl_platform_id platform_id = NULL;
- cl_uint num_platforms_unused;
- int err = clGetPlatformIDs(1, &platform_id, &num_platforms_unused);
- if (err != 0) {
- fprintf(stderr, "cl error: %d\n", err);
- }
- assert(err == 0);
-
- cl_device_id device_id = NULL;
- cl_uint num_devices_unused;
- err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &device_id,
- &num_devices_unused);
- if (err != 0) {
- fprintf(stderr, "cl error: %d\n", err);
- }
- assert(err == 0);
-
- cl_print_info(platform_id, device_id);
- printf("\n");
-
+ int err;
+ cl_device_id device_id = cl_get_device_id(CL_DEVICE_TYPE_DEFAULT);
cl_context context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &err);
assert(err == 0);
diff --git a/selfdrive/camerad/transforms/rgb_to_yuv.c b/selfdrive/camerad/transforms/rgb_to_yuv.c
index b9e66b36db..1a36650b9f 100644
--- a/selfdrive/camerad/transforms/rgb_to_yuv.c
+++ b/selfdrive/camerad/transforms/rgb_to_yuv.c
@@ -43,7 +43,7 @@ void rgb_to_yuv_queue(RGBToYUVState* s, cl_command_queue q, cl_mem rgb_cl, cl_me
err = clSetKernelArg(s->rgb_to_yuv_krnl, 1, sizeof(cl_mem), &yuv_cl);
assert(err == 0);
const size_t work_size[2] = {
- (size_t)(s->width + (s->width % 4 == 0 ? 0 : (4 - s->width % 4))) / 4,
+ (size_t)(s->width + (s->width % 4 == 0 ? 0 : (4 - s->width % 4))) / 4,
(size_t)(s->height + (s->height % 4 == 0 ? 0 : (4 - s->height % 4))) / 4
};
cl_event event;
diff --git a/selfdrive/camerad/transforms/rgb_to_yuv_test.cc b/selfdrive/camerad/transforms/rgb_to_yuv_test.cc
index c8b8751058..9d68e5b9ef 100644
--- a/selfdrive/camerad/transforms/rgb_to_yuv_test.cc
+++ b/selfdrive/camerad/transforms/rgb_to_yuv_test.cc
@@ -42,14 +42,7 @@ static inline double millis_since_boot() {
void cl_init(cl_device_id &device_id, cl_context &context) {
int err;
- cl_platform_id platform_id = NULL;
- cl_uint num_devices;
- cl_uint num_platforms;
-
- err = clGetPlatformIDs(1, &platform_id, &num_platforms);
- err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1,
- &device_id, &num_devices);
- cl_print_info(platform_id, device_id);
+ device_id = cl_get_device_id(CL_DEVICE_TYPE_DEFAULT);
context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &err);
}
diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py
index 6ad29d4b3a..7701f90a6d 100644
--- a/selfdrive/car/__init__.py
+++ b/selfdrive/car/__init__.py
@@ -4,9 +4,11 @@ from common.numpy_fast import clip
# kg of standard extra cargo to count for drive, gas, etc...
STD_CARGO_KG = 136.
+
def gen_empty_fingerprint():
return {i: {} for i in range(0, 4)}
+
# FIXME: hardcoding honda civic 2016 touring params so they can be used to
# scale unknown params for other cars
class CivicParams:
@@ -18,11 +20,13 @@ class CivicParams:
TIRE_STIFFNESS_FRONT = 192150
TIRE_STIFFNESS_REAR = 202500
+
# TODO: get actual value, for now starting with reasonable value for
# civic and scaling by mass and wheelbase
def scale_rot_inertia(mass, wheelbase):
return CivicParams.ROTATIONAL_INERTIA * mass * wheelbase ** 2 / (CivicParams.MASS * CivicParams.WHEELBASE ** 2)
+
# TODO: start from empirically derived lateral slip stiffness for the civic and scale by
# mass and CG position, so all cars will have approximately similar dyn behaviors
def scale_tire_stiffness(mass, wheelbase, center_to_front, tire_stiffness_factor=1.0):
@@ -35,8 +39,9 @@ def scale_tire_stiffness(mass, wheelbase, center_to_front, tire_stiffness_factor
return tire_stiffness_front, tire_stiffness_rear
-def dbc_dict(pt_dbc, radar_dbc, chassis_dbc=None):
- return {'pt': pt_dbc, 'radar': radar_dbc, 'chassis': chassis_dbc}
+
+def dbc_dict(pt_dbc, radar_dbc, chassis_dbc=None, body_dbc=None):
+ return {'pt': pt_dbc, 'radar': radar_dbc, 'chassis': chassis_dbc, 'body': body_dbc}
def apply_std_steer_torque_limits(apply_torque, apply_torque_last, driver_torque, LIMITS):
@@ -51,10 +56,10 @@ def apply_std_steer_torque_limits(apply_torque, apply_torque_last, driver_torque
# slow rate if steer torque increases in magnitude
if apply_torque_last > 0:
apply_torque = clip(apply_torque, max(apply_torque_last - LIMITS.STEER_DELTA_DOWN, -LIMITS.STEER_DELTA_UP),
- apply_torque_last + LIMITS.STEER_DELTA_UP)
+ apply_torque_last + LIMITS.STEER_DELTA_UP)
else:
apply_torque = clip(apply_torque, apply_torque_last - LIMITS.STEER_DELTA_UP,
- min(apply_torque_last + LIMITS.STEER_DELTA_DOWN, LIMITS.STEER_DELTA_UP))
+ min(apply_torque_last + LIMITS.STEER_DELTA_DOWN, LIMITS.STEER_DELTA_UP))
return int(round(float(apply_torque)))
@@ -83,9 +88,9 @@ def crc8_pedal(data):
crc = 0xFF # standard init value
poly = 0xD5 # standard crc8: x8+x7+x6+x4+x2+1
size = len(data)
- for i in range(size-1, -1, -1):
+ for i in range(size - 1, -1, -1):
crc ^= data[i]
- for j in range(8):
+ for _ in range(8):
if ((crc & 0x80) != 0):
crc = ((crc << 1) ^ poly) & 0xFF
else:
@@ -128,4 +133,3 @@ def is_ecu_disconnected(fingerprint, fingerprint_list, ecu_fingerprint, car, ecu
def make_can_msg(addr, dat, bus):
return [addr, 0, dat, bus]
-
diff --git a/selfdrive/car/car_helpers.py b/selfdrive/car/car_helpers.py
index 9052ebb26b..e79b03cc5c 100644
--- a/selfdrive/car/car_helpers.py
+++ b/selfdrive/car/car_helpers.py
@@ -1,6 +1,7 @@
import os
from common.params import Params
from common.basedir import BASEDIR
+from selfdrive.version import comma_remote, tested_branch
from selfdrive.car.fingerprints import eliminate_incompatible_cars, all_known_cars
from selfdrive.car.vin import get_vin, VIN_UNKNOWN
from selfdrive.car.fw_versions import get_fw_versions, match_fw_to_car
@@ -8,14 +9,17 @@ from selfdrive.swaglog import cloudlog
import cereal.messaging as messaging
from selfdrive.car import gen_empty_fingerprint
-from cereal import car
+from cereal import car, log
EventName = car.CarEvent.EventName
+HwType = log.HealthData.HwType
+
def get_startup_event(car_recognized, controller_available):
- event = EventName.startup
- if Params().get("GitRemote", encoding="utf8") in ['git@github.com:commaai/openpilot.git', 'https://github.com/commaai/openpilot.git']:
- if Params().get("GitBranch", encoding="utf8") not in ['devel', 'release2-staging', 'dashcam-staging', 'release2', 'dashcam']:
- event = EventName.startupMaster
+ if comma_remote and tested_branch:
+ event = EventName.startup
+ else:
+ event = EventName.startupMaster
+
if not car_recognized:
event = EventName.startupNoCar
elif car_recognized and not controller_available:
@@ -23,6 +27,13 @@ def get_startup_event(car_recognized, controller_available):
return event
+def get_one_can(logcan):
+ while True:
+ can = messaging.recv_one_retry(logcan)
+ if len(can.can) > 0:
+ return can
+
+
def load_interfaces(brand_names):
ret = {}
for brand_name in brand_names:
@@ -73,8 +84,9 @@ def only_toyota_left(candidate_cars):
# **** for use live only ****
def fingerprint(logcan, sendcan, has_relay):
fixed_fingerprint = os.environ.get('FINGERPRINT', "")
+ skip_fw_query = os.environ.get('SKIP_FW_QUERY', False)
- if has_relay and not fixed_fingerprint:
+ if has_relay and not fixed_fingerprint and not skip_fw_query:
# Vin query only reliably works thorugh OBDII
bus = 1
@@ -109,7 +121,7 @@ def fingerprint(logcan, sendcan, has_relay):
done = False
while not done:
- a = messaging.get_one_can(logcan)
+ a = get_one_can(logcan)
for can in a.can:
# need to independently try to fingerprint both bus 0 and 1 to work
diff --git a/selfdrive/car/chrysler/carcontroller.py b/selfdrive/car/chrysler/carcontroller.py
index c4db730368..b81526e9c0 100644
--- a/selfdrive/car/chrysler/carcontroller.py
+++ b/selfdrive/car/chrysler/carcontroller.py
@@ -11,13 +11,11 @@ class CarController():
self.prev_frame = -1
self.hud_count = 0
self.car_fingerprint = CP.carFingerprint
- self.alert_active = False
self.gone_fast_yet = False
self.steer_rate_limited = False
self.packer = CANPacker(dbc_name)
-
def update(self, enabled, CS, actuators, pcm_cancel_cmd, hud_alert):
# this seems needed to avoid steering faults and to force the sync with the EPS counter
frame = CS.lkas_counter
diff --git a/selfdrive/car/chrysler/carstate.py b/selfdrive/car/chrysler/carstate.py
index 1a4b1e659e..b6fdb11314 100644
--- a/selfdrive/car/chrysler/carstate.py
+++ b/selfdrive/car/chrysler/carstate.py
@@ -24,7 +24,7 @@ class CarState(CarStateBase):
cp.vl["DOORS"]['DOOR_OPEN_RR']])
ret.seatbeltUnlatched = cp.vl["SEATBELT_STATUS"]['SEATBELT_DRIVER_UNLATCHED'] == 1
- ret.brakePressed = cp.vl["BRAKE_2"]['BRAKE_PRESSED_2'] == 5 # human-only
+ ret.brakePressed = cp.vl["BRAKE_2"]['BRAKE_PRESSED_2'] == 5 # human-only
ret.brake = 0
ret.brakeLights = ret.brakePressed
ret.gas = cp.vl["ACCEL_GAS_134"]['ACCEL_134']
@@ -103,6 +103,13 @@ class CarState(CarStateBase):
("WHEEL_SPEEDS", 50),
("STEERING", 100),
("ACC_2", 50),
+ ("GEAR", 50),
+ ("ACCEL_GAS_134", 50),
+ ("DASHBOARD", 15),
+ ("STEERING_LEVERS", 10),
+ ("SEATBELT_STATUS", 2),
+ ("DOORS", 1),
+ ("TRACTION_BUTTON", 1),
]
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 0)
@@ -115,6 +122,10 @@ class CarState(CarStateBase):
("CAR_MODEL", "LKAS_HUD", -1),
("LKAS_STATUS_OK", "LKAS_HEARTBIT", -1)
]
- checks = []
+ checks = [
+ ("LKAS_COMMAND", 100),
+ ("LKAS_HEARTBIT", 10),
+ ("LKAS_HUD", 4),
+ ]
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2)
diff --git a/selfdrive/car/chrysler/chryslercan.py b/selfdrive/car/chrysler/chryslercan.py
index bf9f3731f6..63d1fbe0b4 100644
--- a/selfdrive/car/chrysler/chryslercan.py
+++ b/selfdrive/car/chrysler/chryslercan.py
@@ -16,7 +16,7 @@ def create_lkas_hud(packer, gear, lkas_active, hud_alert, hud_count, lkas_car_mo
lines = 1
alerts = 0
- if hud_count < (1 *4): # first 3 seconds, 4Hz
+ if hud_count < (1 * 4): # first 3 seconds, 4Hz
alerts = 1
# CAR.PACIFICA_2018_HYBRID and CAR.PACIFICA_2019_HYBRID
# had color = 1 and lines = 1 but trying 2017 hybrid style for now.
diff --git a/selfdrive/car/chrysler/interface.py b/selfdrive/car/chrysler/interface.py
index 66ba7159fb..fbc469ebeb 100755
--- a/selfdrive/car/chrysler/interface.py
+++ b/selfdrive/car/chrysler/interface.py
@@ -11,7 +11,10 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 3.0
@staticmethod
- def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]):
+ def get_params(candidate, fingerprint=None, has_relay=False, car_fw=None):
+ if fingerprint is None:
+ fingerprint = gen_empty_fingerprint()
+
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay)
ret.carName = "chrysler"
ret.safetyModel = car.CarParams.SafetyModel.chrysler
@@ -21,10 +24,10 @@ class CarInterface(CarInterfaceBase):
# Speed conversion: 20, 45 mph
ret.wheelbase = 3.089 # in meters for Pacifica Hybrid 2017
- ret.steerRatio = 16.2 # Pacifica Hybrid 2017
+ ret.steerRatio = 16.2 # Pacifica Hybrid 2017
ret.mass = 2858. + STD_CARGO_KG # kg curb weight Pacifica Hybrid 2017
ret.lateralTuning.pid.kpBP, ret.lateralTuning.pid.kiBP = [[9., 20.], [9., 20.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.15,0.30], [0.03,0.05]]
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.15, 0.30], [0.03, 0.05]]
ret.lateralTuning.pid.kf = 0.00006 # full torque for 10 deg at 80mph means 0.00007818594
ret.steerActuatorDelay = 0.1
ret.steerRateCost = 0.7
@@ -67,10 +70,8 @@ class CarInterface(CarInterfaceBase):
# speeds
ret.steeringRateLimited = self.CC.steer_rate_limited if self.CC is not None else False
- ret.buttonEvents = []
-
# events
- events = self.create_common_events(ret, extra_gears=[car.CarState.GearShifter.low], \
+ events = self.create_common_events(ret, extra_gears=[car.CarState.GearShifter.low],
gas_resume_speed=2.)
if ret.vEgo < self.CP.minSteerSpeed:
@@ -88,7 +89,7 @@ class CarInterface(CarInterfaceBase):
def apply(self, c):
if (self.CS.frame == -1):
- return [] # if we haven't seen a frame 220, then do not update.
+ return [] # if we haven't seen a frame 220, then do not update.
can_sends = self.CC.update(c.enabled, self.CS, c.actuators, c.cruiseControl.cancel, c.hudControl.visualAlert)
diff --git a/selfdrive/car/chrysler/radar_interface.py b/selfdrive/car/chrysler/radar_interface.py
index 40a7c5a742..3139efad34 100755
--- a/selfdrive/car/chrysler/radar_interface.py
+++ b/selfdrive/car/chrysler/radar_interface.py
@@ -1,16 +1,15 @@
#!/usr/bin/env python3
-import os
from opendbc.can.parser import CANParser
from cereal import car
from selfdrive.car.interfaces import RadarInterfaceBase
+from selfdrive.car.chrysler.values import DBC
RADAR_MSGS_C = list(range(0x2c2, 0x2d4+2, 2)) # c_ messages 706,...,724
RADAR_MSGS_D = list(range(0x2a2, 0x2b4+2, 2)) # d_ messages
LAST_MSG = max(RADAR_MSGS_C + RADAR_MSGS_D)
NUMBER_MSGS = len(RADAR_MSGS_C) + len(RADAR_MSGS_D)
-def _create_radar_can_parser():
- dbc_f = 'chrysler_pacifica_2017_hybrid_private_fusion.dbc'
+def _create_radar_can_parser(car_fingerprint):
msg_n = len(RADAR_MSGS_C)
# list of [(signal name, message name or number, initial values), (...)]
# [('RADAR_STATE', 1024, 0),
@@ -37,7 +36,7 @@ def _create_radar_can_parser():
[20]*msg_n + # 20Hz (0.05s)
[20]*msg_n)) # 20Hz (0.05s)
- return CANParser(os.path.splitext(dbc_f)[0], signals, checks, 1)
+ return CANParser(DBC[car_fingerprint]['radar'], signals, checks, 1)
def _address_to_track(address):
if address in RADAR_MSGS_C:
@@ -49,7 +48,7 @@ def _address_to_track(address):
class RadarInterface(RadarInterfaceBase):
def __init__(self, CP):
super().__init__(CP)
- self.rcp = _create_radar_can_parser()
+ self.rcp = _create_radar_can_parser(CP.carFingerprint)
self.updated_messages = set()
self.trigger_msg = LAST_MSG
diff --git a/selfdrive/car/chrysler/test_chryslercan.py b/selfdrive/car/chrysler/test_chryslercan.py
deleted file mode 100644
index 5b15666c04..0000000000
--- a/selfdrive/car/chrysler/test_chryslercan.py
+++ /dev/null
@@ -1,57 +0,0 @@
-import unittest
-
-from cereal import car
-from opendbc.can.packer import CANPacker
-from selfdrive.car.chrysler import chryslercan
-
-VisualAlert = car.CarControl.HUDControl.VisualAlert
-GearShifter = car.CarState.GearShifter
-
-
-
-class TestChryslerCan(unittest.TestCase):
-
- def test_hud(self):
- packer = CANPacker('chrysler_pacifica_2017_hybrid')
- self.assertEqual(
- [0x2a6, 0, b'\x01\x00\x01\x01\x00\x00\x00\x00', 0],
- chryslercan.create_lkas_hud(
- packer,
- GearShifter.park, False, False, 1, 0))
- self.assertEqual(
- [0x2a6, 0, b'\x01\x00\x01\x00\x00\x00\x00\x00', 0],
- chryslercan.create_lkas_hud(
- packer,
- GearShifter.park, False, False, 5*4, 0))
- self.assertEqual(
- [0x2a6, 0, b'\x01\x00\x01\x00\x00\x00\x00\x00', 0],
- chryslercan.create_lkas_hud(
- packer,
- GearShifter.park, False, False, 99999, 0))
- self.assertEqual(
- [0x2a6, 0, b'\x02\x00\x06\x00\x00\x00\x00\x00', 0],
- chryslercan.create_lkas_hud(
- packer,
- GearShifter.drive, True, False, 99999, 0))
- self.assertEqual(
- [0x2a6, 0, b'\x02\x64\x06\x00\x00\x00\x00\x00', 0],
- chryslercan.create_lkas_hud(
- packer,
- GearShifter.drive, True, False, 99999, 0x64))
-
- def test_command(self):
- packer = CANPacker('chrysler_pacifica_2017_hybrid')
- self.assertEqual(
- [0x292, 0, b'\x14\x00\x00\x00\x10\x86', 0],
- chryslercan.create_lkas_command(
- packer,
- 0, True, 1))
- self.assertEqual(
- [0x292, 0, b'\x04\x00\x00\x00\x80\x83', 0],
- chryslercan.create_lkas_command(
- packer,
- 0, False, 8))
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py
index ac1ede5f9f..b7fb53f530 100644
--- a/selfdrive/car/chrysler/values.py
+++ b/selfdrive/car/chrysler/values.py
@@ -1,8 +1,9 @@
+# flake8: noqa
+
from selfdrive.car import dbc_dict
from cereal import car
Ecu = car.CarParams.Ecu
-
class SteerLimitParams:
STEER_MAX = 261 # 262 faults
STEER_DELTA_UP = 3 # 3 is stock. 100 is fine. 200 is too much it seems
@@ -10,15 +11,14 @@ class SteerLimitParams:
STEER_ERROR_MAX = 80
-
class CAR:
PACIFICA_2017_HYBRID = "CHRYSLER PACIFICA HYBRID 2017"
PACIFICA_2018_HYBRID = "CHRYSLER PACIFICA HYBRID 2018"
PACIFICA_2019_HYBRID = "CHRYSLER PACIFICA HYBRID 2019"
- PACIFICA_2018 = "CHRYSLER PACIFICA 2018" # Also covers Pacifica 2017.
+ PACIFICA_2018 = "CHRYSLER PACIFICA 2018" # includes 2017 Pacifica
PACIFICA_2020 = "CHRYSLER PACIFICA 2020"
- JEEP_CHEROKEE = "JEEP GRAND CHEROKEE V6 2018" # Also covers Tailhawk 2017.
- JEEP_CHEROKEE_2019 = "JEEP GRAND CHEROKEE 2019"
+ JEEP_CHEROKEE = "JEEP GRAND CHEROKEE V6 2018" # includes 2017 Trailhawk
+ JEEP_CHEROKEE_2019 = "JEEP GRAND CHEROKEE 2019" # includes 2020 Trailhawk
# Unique can messages:
# Only the hybrids have 270: 8
@@ -41,7 +41,7 @@ FINGERPRINTS = {
],
CAR.PACIFICA_2020: [
{
- 55: 8, 179: 8, 181: 8, 257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 528: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 650: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 676: 8, 678: 8, 680: 8, 683: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 847: 1, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 906: 8, 924: 8, 926: 3, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1098: 8, 1100: 8, 1216: 8, 1218: 8, 1220: 8, 1223: 7, 1225: 8, 1235: 8, 1242: 8, 1246: 8, 1250: 8, 1251: 8, 1252: 8, 1284: 8, 1568: 8, 1856: 8, 1858: 8, 1860: 8, 1863: 8, 1865: 8, 1875: 8, 1882: 8, 1886: 8, 1890: 8, 1891: 8, 1892: 8, 2016: 8, 2024: 8
+ 55: 8, 179: 8, 181: 8, 257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 528: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 650: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 676: 8, 678: 8, 680: 8, 683: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 847: 1, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 906: 8, 924: 8, 926: 3, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1098: 8, 1100: 8, 1216: 8, 1218: 8, 1220: 8, 1223: 7, 1225: 8, 1235: 8, 1242: 8, 1246: 8, 1250: 8, 1251: 8, 1252: 8, 1284: 8, 1568: 8, 1570: 8, 1856: 8, 1858: 8, 1860: 8, 1863: 8, 1865: 8, 1875: 8, 1882: 8, 1886: 8, 1890: 8, 1891: 8, 1892: 8, 2016: 8, 2024: 8
}
],
CAR.PACIFICA_2018_HYBRID: [
@@ -50,7 +50,7 @@ FINGERPRINTS = {
{168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 515: 7, 516: 7, 517: 7, 518: 7, 520: 8, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 701: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 746: 5, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8, 1216: 8, 1218: 8, 1220: 8, 1225: 8, 1235: 8, 1242: 8, 1246: 8, 1250: 8, 1251: 8, 1252: 8, 1258: 8, 1259: 8, 1260: 8, 1262: 8, 1284: 8, 1537: 8, 1538: 8, 1562: 8, 1568: 8, 1856: 8, 1858: 8, 1860: 8, 1865: 8, 1875: 8, 1882: 8, 1886: 8, 1890: 8, 1891: 8, 1892: 8, 1898: 8, 1899: 8, 1900: 8, 1902: 8, 2016: 8, 2018: 8, 2019: 8, 2020: 8, 2023: 8, 2024: 8, 2026: 8, 2027: 8, 2028: 8, 2031: 8},
],
CAR.PACIFICA_2019_HYBRID: [
- {168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 515: 7, 516: 7, 517: 7, 518: 7, 520: 8, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 680: 8, 701: 8, 703: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770:8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 906: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8, 1538: 8},
+ {168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 515: 7, 516: 7, 517: 7, 518: 7, 520: 8, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 680: 8, 701: 8, 703: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 906: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8, 1538: 8},
# Based on 0607d2516fc2148f|2019-02-13--23-03-16
{
168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 528: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 701: 8, 703: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 906: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8, 1537: 8
@@ -74,40 +74,25 @@ FINGERPRINTS = {
{257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 4, 571: 3, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 658: 6, 660: 8, 671: 8, 672: 8, 680: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 752: 2, 760: 8, 761: 8, 764: 8, 766: 8, 773: 8, 776: 8, 779: 8, 783: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 806: 2, 808: 8, 810: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 844: 5, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 924: 3, 937: 8, 947: 8, 948: 8, 969: 4, 974: 5, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8},
],
CAR.JEEP_CHEROKEE_2019: [
- # Jeep Grand Cherokee 2019
- # 530: 8 is so far only in this Jeep.
- {55: 8, 168: 8, 181: 8, 256: 4, 257: 5, 258: 8, 264: 8, 268: 8, 272: 6, 273: 6, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 530: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 656: 4, 658: 6, 660: 8, 671: 8, 672: 8, 676: 8, 678: 8, 680: 8, 683: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 738: 8, 746: 5, 752: 2, 754: 8, 760: 8, 761: 8, 764: 8, 766: 8, 773: 8, 776: 8, 779: 8, 782: 8, 783: 8, 784: 8, 785: 8, 792: 8, 799: 8, 800: 8, 804: 8, 806: 2, 808: 8, 810: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 840: 8, 844: 5, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 906: 8, 924: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 968: 8, 969: 4, 970: 8, 973: 8, 974: 5, 976: 8, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8, 1543: 8, 2015: 8, 2016: 8, 2024: 8},
+ # Jeep Grand Cherokee 2019, including most 2020 models
+ {55: 8, 168: 8, 179: 8, 181: 8, 256: 4, 257: 5, 258: 8, 264: 8, 268: 8, 272: 6, 273: 6, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 341: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 530: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 640: 1, 656: 4, 658: 6, 660: 8, 671: 8, 672: 8, 676: 8, 678: 8, 680: 8, 683: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 738: 8, 746: 5, 752: 2, 754: 8, 760: 8, 761: 8, 764: 8, 766: 8, 773: 8, 776: 8, 779: 8, 782: 8, 783: 8, 784: 8, 785: 8, 792: 8, 799: 8, 800: 8, 804: 8, 806: 2, 808: 8, 810: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 840: 8, 844: 5, 847: 1, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 906: 8, 924: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 960: 4, 968: 8, 969: 4, 970: 8, 973: 8, 974: 5, 976: 8, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8, 1216: 8, 1218: 8, 1220: 8, 1223: 8, 1225: 8, 1227: 8, 1235: 8, 1242: 8, 1250: 8, 1251: 8, 1252: 8, 1254: 8, 1264: 8, 1284: 8, 1536: 8, 1537: 8, 1543: 8, 1545: 8, 1562: 8, 1568: 8, 1570: 8, 1572: 8, 1593: 8, 1856: 8, 1858: 8, 1860: 8, 1863: 8, 1865: 8, 1867: 8, 1875: 8, 1882: 8, 1890: 8, 1891: 8, 1892: 8, 1894: 8, 1896: 8, 1904: 8, 2015: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8},
],
}
DBC = {
- CAR.PACIFICA_2017_HYBRID: dbc_dict(
- 'chrysler_pacifica_2017_hybrid', # 'pt'
- 'chrysler_pacifica_2017_hybrid_private_fusion'), # 'radar'
- CAR.PACIFICA_2018: dbc_dict( # Same DBC file works.
- 'chrysler_pacifica_2017_hybrid', # 'pt'
- 'chrysler_pacifica_2017_hybrid_private_fusion'), # 'radar'
- CAR.PACIFICA_2020: dbc_dict( # Same DBC file works.
- 'chrysler_pacifica_2017_hybrid', # 'pt'
- 'chrysler_pacifica_2017_hybrid_private_fusion'), # 'radar'
- CAR.PACIFICA_2018_HYBRID: dbc_dict( # Same DBC file works.
- 'chrysler_pacifica_2017_hybrid', # 'pt'
- 'chrysler_pacifica_2017_hybrid_private_fusion'), # 'radar'
- CAR.PACIFICA_2019_HYBRID: dbc_dict( # Same DBC file works.
- 'chrysler_pacifica_2017_hybrid', # 'pt'
- 'chrysler_pacifica_2017_hybrid_private_fusion'), # 'radar'
- CAR.JEEP_CHEROKEE: dbc_dict( # Same DBC file works.
- 'chrysler_pacifica_2017_hybrid', # 'pt'
- 'chrysler_pacifica_2017_hybrid_private_fusion'), # 'radar'
- CAR.JEEP_CHEROKEE_2019: dbc_dict( # Same DBC file works.
- 'chrysler_pacifica_2017_hybrid', # 'pt'
- 'chrysler_pacifica_2017_hybrid_private_fusion'), # 'radar'
+ CAR.PACIFICA_2017_HYBRID: dbc_dict('chrysler_pacifica_2017_hybrid', 'chrysler_pacifica_2017_hybrid_private_fusion'),
+ CAR.PACIFICA_2018: dbc_dict('chrysler_pacifica_2017_hybrid', 'chrysler_pacifica_2017_hybrid_private_fusion'),
+ CAR.PACIFICA_2020: dbc_dict('chrysler_pacifica_2017_hybrid', 'chrysler_pacifica_2017_hybrid_private_fusion'),
+ CAR.PACIFICA_2018_HYBRID: dbc_dict('chrysler_pacifica_2017_hybrid', 'chrysler_pacifica_2017_hybrid_private_fusion'),
+ CAR.PACIFICA_2019_HYBRID: dbc_dict('chrysler_pacifica_2017_hybrid', 'chrysler_pacifica_2017_hybrid_private_fusion'),
+ CAR.JEEP_CHEROKEE: dbc_dict('chrysler_pacifica_2017_hybrid', 'chrysler_pacifica_2017_hybrid_private_fusion'),
+ CAR.JEEP_CHEROKEE_2019: dbc_dict('chrysler_pacifica_2017_hybrid', 'chrysler_pacifica_2017_hybrid_private_fusion'),
}
STEER_THRESHOLD = 120
ECU_FINGERPRINT = {
- Ecu.fwdCamera: [0x292], # lkas cmd
+ Ecu.fwdCamera: [0x292], # lkas cmd
}
diff --git a/selfdrive/car/fingerprints.py b/selfdrive/car/fingerprints.py
index c2c39f687f..64dc56625c 100644
--- a/selfdrive/car/fingerprints.py
+++ b/selfdrive/car/fingerprints.py
@@ -2,7 +2,7 @@ import os
from common.basedir import BASEDIR
-def get_attr_from_cars(attr, result=dict):
+def get_attr_from_cars(attr, result=dict, combine_brands=True):
# read all the folders in selfdrive/car and return a dict where:
# - keys are all the car models
# - values are attr values from all car folders
@@ -19,7 +19,12 @@ def get_attr_from_cars(attr, result=dict):
if isinstance(attr_values, dict):
for f, v in attr_values.items():
- result[f] = v
+ if combine_brands:
+ result[f] = v
+ else:
+ if car_name not in result:
+ result[car_name] = {}
+ result[car_name][f] = v
elif isinstance(attr_values, list):
result += attr_values
diff --git a/selfdrive/car/ford/carcontroller.py b/selfdrive/car/ford/carcontroller.py
index 4c0a37ab02..648fa07741 100644
--- a/selfdrive/car/ford/carcontroller.py
+++ b/selfdrive/car/ford/carcontroller.py
@@ -78,7 +78,7 @@ class CarController():
static_msgs = range(1653, 1658)
for addr in static_msgs:
cnt = (frame % 10) + 1
- can_sends.append(make_can_msg(addr, (cnt<<4).to_bytes(1, 'little') + b'\x00\x00\x00\x00\x00\x00\x00', 1))
+ can_sends.append(make_can_msg(addr, (cnt << 4).to_bytes(1, 'little') + b'\x00\x00\x00\x00\x00\x00\x00', 1))
self.enabled_last = enabled
self.main_on_last = CS.out.cruiseState.available
diff --git a/selfdrive/car/ford/fordcan.py b/selfdrive/car/ford/fordcan.py
index dd0c15415e..e98dec584b 100644
--- a/selfdrive/car/ford/fordcan.py
+++ b/selfdrive/car/ford/fordcan.py
@@ -6,7 +6,7 @@ def create_steer_command(packer, angle_cmd, enabled, lkas_state, angle_steers, c
"""Creates a CAN message for the Ford Steer Command."""
#if enabled and lkas available:
- if enabled and lkas_state in [2,3]: #and (frame % 500) >= 3:
+ if enabled and lkas_state in [2, 3]: # and (frame % 500) >= 3:
action = lkas_action
else:
action = 0xf
diff --git a/selfdrive/car/ford/interface.py b/selfdrive/car/ford/interface.py
index 4388ae7962..6d6c82f0b8 100755
--- a/selfdrive/car/ford/interface.py
+++ b/selfdrive/car/ford/interface.py
@@ -14,7 +14,7 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 3.0
@staticmethod
- def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]):
+ def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay)
ret.carName = "ford"
ret.safetyModel = car.CarParams.SafetyModel.ford
@@ -60,7 +60,7 @@ class CarInterface(CarInterfaceBase):
# events
events = self.create_common_events(ret)
- if self.CS.lkas_state not in [2, 3] and ret.vEgo > 13.* CV.MPH_TO_MS and ret.cruiseState.enabled:
+ if self.CS.lkas_state not in [2, 3] and ret.vEgo > 13. * CV.MPH_TO_MS and ret.cruiseState.enabled:
events.add(car.CarEvent.EventName.steerTempUnavailableMute)
ret.events = events.to_msg()
diff --git a/selfdrive/car/ford/radar_interface.py b/selfdrive/car/ford/radar_interface.py
index 3733ddce7f..20a435b082 100755
--- a/selfdrive/car/ford/radar_interface.py
+++ b/selfdrive/car/ford/radar_interface.py
@@ -8,14 +8,13 @@ from selfdrive.car.interfaces import RadarInterfaceBase
RADAR_MSGS = list(range(0x500, 0x540))
def _create_radar_can_parser(car_fingerprint):
- dbc_f = DBC[car_fingerprint]['radar']
msg_n = len(RADAR_MSGS)
signals = list(zip(['X_Rel'] * msg_n + ['Angle'] * msg_n + ['V_Rel'] * msg_n,
RADAR_MSGS * 3,
[0] * msg_n + [0] * msg_n + [0] * msg_n))
checks = list(zip(RADAR_MSGS, [20]*msg_n))
- return CANParser(dbc_f, signals, checks, 1)
+ return CANParser(DBC[car_fingerprint]['radar'], signals, checks, 1)
class RadarInterface(RadarInterfaceBase):
def __init__(self, CP):
@@ -34,7 +33,6 @@ class RadarInterface(RadarInterfaceBase):
if self.trigger_msg not in self.updated_messages:
return None
-
ret = car.RadarData.new_message()
errors = []
if not self.rcp.can_valid:
@@ -50,7 +48,7 @@ class RadarInterface(RadarInterfaceBase):
if cpt['X_Rel'] > 0.00001:
self.validCnt[ii] += 1
else:
- self.validCnt[ii] = max(self.validCnt[ii] -1, 0)
+ self.validCnt[ii] = max(self.validCnt[ii] - 1, 0)
#print ii, self.validCnt[ii], cpt['VALID'], cpt['X_Rel'], cpt['Angle']
# radar point only valid if there have been enough valid measurements
diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py
index 191f06cbc8..7c4d0aed98 100644
--- a/selfdrive/car/ford/values.py
+++ b/selfdrive/car/ford/values.py
@@ -1,3 +1,5 @@
+# flake8: noqa
+
from selfdrive.car import dbc_dict
from cereal import car
Ecu = car.CarParams.Ecu
diff --git a/selfdrive/car/fw_versions.py b/selfdrive/car/fw_versions.py
index 95b970f125..ca53460520 100755
--- a/selfdrive/car/fw_versions.py
+++ b/selfdrive/car/fw_versions.py
@@ -1,20 +1,24 @@
#!/usr/bin/env python3
-import traceback
import struct
+import traceback
+from typing import Any
+
from tqdm import tqdm
+import panda.python.uds as uds
+from cereal import car
+from selfdrive.car.fingerprints import FW_VERSIONS, get_attr_from_cars
from selfdrive.car.isotp_parallel_query import IsoTpParallelQuery
-from selfdrive.swaglog import cloudlog
-from selfdrive.car.fingerprints import FW_VERSIONS
from selfdrive.car.toyota.values import CAR as TOYOTA
-import panda.python.uds as uds
+from selfdrive.swaglog import cloudlog
-from cereal import car
Ecu = car.CarParams.Ecu
+
def p16(val):
return struct.pack("!H", val)
+
TESTER_PRESENT_REQUEST = bytes([uds.SERVICE_TYPE.TESTER_PRESENT, 0x0])
TESTER_PRESENT_RESPONSE = bytes([uds.SERVICE_TYPE.TESTER_PRESENT + 0x40, 0x0])
@@ -36,6 +40,19 @@ UDS_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \
UDS_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \
p16(uds.DATA_IDENTIFIER_TYPE.APPLICATION_SOFTWARE_IDENTIFICATION)
+
+HYUNDAI_VERSION_REQUEST_SHORT = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \
+ p16(0xf1a0) # 4 Byte version number
+HYUNDAI_VERSION_REQUEST_LONG = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \
+ p16(0xf100) # Long description
+HYUNDAI_VERSION_REQUEST_MULTI = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \
+ p16(uds.DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_SPARE_PART_NUMBER) + \
+ p16(uds.DATA_IDENTIFIER_TYPE.APPLICATION_SOFTWARE_IDENTIFICATION) + \
+ p16(0xf100) + \
+ p16(0xf1a0)
+HYUNDAI_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40])
+
+
TOYOTA_VERSION_REQUEST = b'\x1a\x88\x01'
TOYOTA_VERSION_RESPONSE = b'\x5a\x88\x01'
@@ -43,24 +60,45 @@ OBD_VERSION_REQUEST = b'\x09\x04'
OBD_VERSION_RESPONSE = b'\x49\x04'
+# supports subaddressing, request, response
REQUESTS = [
+ # Hundai
+ (
+ "hyundai",
+ [HYUNDAI_VERSION_REQUEST_SHORT],
+ [HYUNDAI_VERSION_RESPONSE],
+ ),
+ (
+ "hyundai",
+ [HYUNDAI_VERSION_REQUEST_LONG],
+ [HYUNDAI_VERSION_RESPONSE],
+ ),
+ (
+ "hyundai",
+ [HYUNDAI_VERSION_REQUEST_MULTI],
+ [HYUNDAI_VERSION_RESPONSE],
+ ),
# Honda
(
+ "honda",
[UDS_VERSION_REQUEST],
- [UDS_VERSION_RESPONSE]
+ [UDS_VERSION_RESPONSE],
),
# Toyota
(
+ "toyota",
[SHORT_TESTER_PRESENT_REQUEST, TOYOTA_VERSION_REQUEST],
- [SHORT_TESTER_PRESENT_RESPONSE, TOYOTA_VERSION_RESPONSE]
+ [SHORT_TESTER_PRESENT_RESPONSE, TOYOTA_VERSION_RESPONSE],
),
(
+ "toyota",
[SHORT_TESTER_PRESENT_REQUEST, OBD_VERSION_REQUEST],
- [SHORT_TESTER_PRESENT_RESPONSE, OBD_VERSION_RESPONSE]
+ [SHORT_TESTER_PRESENT_RESPONSE, OBD_VERSION_RESPONSE],
),
(
+ "toyota",
[TESTER_PRESENT_REQUEST, DEFAULT_DIAGNOSTIC_REQUEST, EXTENDED_DIAGNOSTIC_REQUEST, UDS_VERSION_REQUEST],
- [TESTER_PRESENT_RESPONSE, DEFAULT_DIAGNOSTIC_RESPONSE, EXTENDED_DIAGNOSTIC_RESPONSE, UDS_VERSION_RESPONSE]
+ [TESTER_PRESENT_RESPONSE, DEFAULT_DIAGNOSTIC_RESPONSE, EXTENDED_DIAGNOSTIC_RESPONSE, UDS_VERSION_RESPONSE],
)
]
@@ -112,33 +150,37 @@ def get_fw_versions(logcan, sendcan, bus, extra=None, timeout=0.1, debug=False,
addrs = []
parallel_addrs = []
- versions = FW_VERSIONS
+ versions = get_attr_from_cars('FW_VERSIONS', combine_brands=False)
if extra is not None:
versions.update(extra)
- for c in versions.values():
- for ecu_type, addr, sub_addr in c.keys():
- a = (addr, sub_addr)
- if a not in ecu_types:
- ecu_types[a] = ecu_type
+ for brand, brand_versions in versions.items():
+ for c in brand_versions.values():
+ for ecu_type, addr, sub_addr in c.keys():
+ a = (brand, addr, sub_addr)
+ if a not in ecu_types:
+ ecu_types[(addr, sub_addr)] = ecu_type
- if sub_addr is None:
- if a not in parallel_addrs:
- parallel_addrs.append(a)
- else:
- if [a] not in addrs:
- addrs.append([a])
+ if sub_addr is None:
+ if a not in parallel_addrs:
+ parallel_addrs.append(a)
+ else:
+ if [a] not in addrs:
+ addrs.append([a])
addrs.insert(0, parallel_addrs)
fw_versions = {}
for i, addr in enumerate(tqdm(addrs, disable=not progress)):
for addr_chunk in chunks(addr):
- for request, response in REQUESTS:
+ for brand, request, response in REQUESTS:
try:
- query = IsoTpParallelQuery(sendcan, logcan, bus, addr_chunk, request, response, debug=debug)
- t = 2 * timeout if i == 0 else timeout
- fw_versions.update(query.get_data(t))
+ addrs = [(a, s) for (b, a, s) in addr_chunk if b in (brand, 'any')]
+
+ if addrs:
+ query = IsoTpParallelQuery(sendcan, logcan, bus, addrs, request, response, debug=debug)
+ t = 2 * timeout if i == 0 else timeout
+ fw_versions.update(query.get_data(t))
except Exception:
cloudlog.warning(f"FW query exception: {traceback.format_exc()}")
@@ -173,14 +215,15 @@ if __name__ == "__main__":
logcan = messaging.sub_sock('can')
sendcan = messaging.pub_sock('sendcan')
- extra = None
+ extra: Any = None
if args.scan:
- extra = {"DEBUG": {}}
+ extra = {}
# Honda
for i in range(256):
- extra["DEBUG"][(Ecu.unknown, 0x18da00f1 + (i << 8), None)] = []
- extra["DEBUG"][(Ecu.unknown, 0x700 + i, None)] = []
- extra["DEBUG"][(Ecu.unknown, 0x750, i)] = []
+ extra[(Ecu.unknown, 0x18da00f1 + (i << 8), None)] = []
+ extra[(Ecu.unknown, 0x700 + i, None)] = []
+ extra[(Ecu.unknown, 0x750, i)] = []
+ extra = {"any": {"debug": extra}}
time.sleep(1.)
diff --git a/selfdrive/car/gm/carcontroller.py b/selfdrive/car/gm/carcontroller.py
index bda8ef22cd..9b8e68fee4 100644
--- a/selfdrive/car/gm/carcontroller.py
+++ b/selfdrive/car/gm/carcontroller.py
@@ -20,7 +20,7 @@ class CarControllerParams():
self.STEER_DRIVER_ALLOWANCE = 50 # allowed driver torque before start limiting
self.STEER_DRIVER_MULTIPLIER = 4 # weight driver torque heavily
self.STEER_DRIVER_FACTOR = 100 # from dbc
- self.NEAR_STOP_BRAKE_PHASE = 0.5 # m/s, more aggressive braking near full stop
+ self.NEAR_STOP_BRAKE_PHASE = 0.5 # m/s, more aggressive braking near full stop
# Takes case of "Service Adaptive Cruise" and "Service Front Camera"
# dashboard messages.
@@ -38,24 +38,8 @@ class CarControllerParams():
self.BRAKE_LOOKUP_V = [MAX_BRAKE, 0]
-def actuator_hystereses(final_pedal, pedal_steady):
- # hyst params... TODO: move these to VehicleParams
- pedal_hyst_gap = 0.01 # don't change pedal command for small oscillations within this value
-
- # for small pedal oscillations within pedal_hyst_gap, don't change the pedal command
- if final_pedal == 0.:
- pedal_steady = 0.
- elif final_pedal > pedal_steady + pedal_hyst_gap:
- pedal_steady = final_pedal - pedal_hyst_gap
- elif final_pedal < pedal_steady - pedal_hyst_gap:
- pedal_steady = final_pedal + pedal_hyst_gap
- final_pedal = pedal_steady
-
- return final_pedal, pedal_steady
-
class CarController():
def __init__(self, dbc_name, CP, VM):
- self.pedal_steady = 0.
self.start_time = 0.
self.apply_steer_last = 0
self.lka_icon_status_last = (False, False)
@@ -64,9 +48,10 @@ class CarController():
self.params = CarControllerParams()
self.packer_pt = CANPacker(DBC[CP.carFingerprint]['pt'])
+ self.packer_obj = CANPacker(DBC[CP.carFingerprint]['radar'])
self.packer_ch = CANPacker(DBC[CP.carFingerprint]['chassis'])
- def update(self, enabled, CS, frame, actuators, \
+ def update(self, enabled, CS, frame, actuators,
hud_v_cruise, hud_show_lanes, hud_show_car, hud_alert):
P = self.params
@@ -74,8 +59,7 @@ class CarController():
# Send CAN commands.
can_sends = []
- ### STEER ###
-
+ # STEER
if (frame % P.STEER_STEP) == 0:
lkas_enabled = enabled and not CS.out.steerWarning and CS.out.vEgo > P.MIN_STEER_SPEED
if lkas_enabled:
@@ -88,19 +72,13 @@ class CarController():
self.apply_steer_last = apply_steer
idx = (frame // P.STEER_STEP) % 4
- can_sends.append(gmcan.create_steering_control(self.packer_pt,
- CanBus.POWERTRAIN, apply_steer, idx, lkas_enabled))
-
- ### GAS/BRAKE ###
+ can_sends.append(gmcan.create_steering_control(self.packer_pt, CanBus.POWERTRAIN, apply_steer, idx, lkas_enabled))
+ # GAS/BRAKE
# no output if not enabled, but keep sending keepalive messages
# treat pedals as one
final_pedal = actuators.gas - actuators.brake
- # *** apply pedal hysteresis ***
- final_brake, self.brake_steady = actuator_hystereses(
- final_pedal, self.pedal_steady)
-
if not enabled:
# Stock ECU sends max regen when not enabled.
apply_gas = P.MAX_ACC_REGEN
@@ -116,13 +94,12 @@ class CarController():
at_full_stop = enabled and CS.out.standstill
near_stop = enabled and (CS.out.vEgo < P.NEAR_STOP_BRAKE_PHASE)
can_sends.append(gmcan.create_friction_brake_command(self.packer_ch, CanBus.CHASSIS, apply_brake, idx, near_stop, at_full_stop))
-
- at_full_stop = enabled and CS.out.standstill
can_sends.append(gmcan.create_gas_regen_command(self.packer_pt, CanBus.POWERTRAIN, apply_gas, idx, enabled, at_full_stop))
# Send dashboard UI commands (ACC status), 25hz
if (frame % 4) == 0:
- can_sends.append(gmcan.create_acc_dashboard_command(self.packer_pt, CanBus.POWERTRAIN, enabled, hud_v_cruise * CV.MS_TO_KPH, hud_show_car))
+ send_fcw = hud_alert == VisualAlert.fcw
+ can_sends.append(gmcan.create_acc_dashboard_command(self.packer_pt, CanBus.POWERTRAIN, enabled, hud_v_cruise * CV.MS_TO_KPH, hud_show_car, send_fcw))
# Radar needs to know current speed and yaw rate (50hz),
# and that ADAS is alive (10hz)
@@ -132,7 +109,7 @@ class CarController():
if frame % time_and_headlights_step == 0:
idx = (frame // time_and_headlights_step) % 4
can_sends.append(gmcan.create_adas_time_status(CanBus.OBSTACLE, int((tt - self.start_time) * 60), idx))
- can_sends.append(gmcan.create_adas_headlights_status(CanBus.OBSTACLE))
+ can_sends.append(gmcan.create_adas_headlights_status(self.packer_obj, CanBus.OBSTACLE))
speed_and_accelerometer_step = 2
if frame % speed_and_accelerometer_step == 0:
@@ -150,8 +127,7 @@ class CarController():
lka_active = CS.lkas_status == 1
lka_critical = lka_active and abs(actuators.steer) > 0.9
lka_icon_status = (lka_active, lka_critical)
- if frame % P.CAMERA_KEEPALIVE_STEP == 0 \
- or lka_icon_status != self.lka_icon_status_last:
+ if frame % P.CAMERA_KEEPALIVE_STEP == 0 or lka_icon_status != self.lka_icon_status_last:
steer_alert = hud_alert == VisualAlert.steerRequired
can_sends.append(gmcan.create_lka_icon_command(CanBus.SW_GMLAN, lka_active, lka_critical, steer_alert))
self.lka_icon_status_last = lka_icon_status
diff --git a/selfdrive/car/gm/carstate.py b/selfdrive/car/gm/carstate.py
index ac866ba226..7f45e7ea9e 100644
--- a/selfdrive/car/gm/carstate.py
+++ b/selfdrive/car/gm/carstate.py
@@ -5,8 +5,7 @@ from opendbc.can.can_define import CANDefine
from opendbc.can.parser import CANParser
from selfdrive.car.interfaces import CarStateBase
from selfdrive.car.gm.values import DBC, CAR, AccState, CanBus, \
- CruiseButtons, is_eps_status_ok, \
- STEER_THRESHOLD
+ CruiseButtons, STEER_THRESHOLD
class CarState(CarStateBase):
@@ -44,9 +43,9 @@ class CarState(CarStateBase):
# 1 - open, 0 - closed
ret.doorOpen = (pt_cp.vl["BCMDoorBeltStatus"]['FrontLeftDoor'] == 1 or
- pt_cp.vl["BCMDoorBeltStatus"]['FrontRightDoor'] == 1 or
- pt_cp.vl["BCMDoorBeltStatus"]['RearLeftDoor'] == 1 or
- pt_cp.vl["BCMDoorBeltStatus"]['RearRightDoor'] == 1)
+ pt_cp.vl["BCMDoorBeltStatus"]['FrontRightDoor'] == 1 or
+ pt_cp.vl["BCMDoorBeltStatus"]['RearLeftDoor'] == 1 or
+ pt_cp.vl["BCMDoorBeltStatus"]['RearRightDoor'] == 1)
# 1 - latched
ret.seatbeltUnlatched = pt_cp.vl["BCMDoorBeltStatus"]['LeftSeatBelt'] == 0
@@ -58,18 +57,17 @@ class CarState(CarStateBase):
ret.espDisabled = pt_cp.vl["ESPStatus"]['TractionControlOn'] != 1
self.pcm_acc_status = pt_cp.vl["AcceleratorPedal2"]['CruiseState']
- regen_pressed = False
+ ret.brakePressed = ret.brake > 1e-5
+ # Regen braking is braking
if self.car_fingerprint == CAR.VOLT:
- regen_pressed = bool(pt_cp.vl["EBCMRegenPaddle"]['RegenPaddle'])
+ ret.brakePressed = ret.brakePressed or bool(pt_cp.vl["EBCMRegenPaddle"]['RegenPaddle'])
- # Regen braking is braking
- ret.brakePressed = ret.brake > 1e-5 or regen_pressed
ret.cruiseState.enabled = self.pcm_acc_status != AccState.OFF
ret.cruiseState.standstill = self.pcm_acc_status == AccState.STANDSTILL
# 0 - inactive, 1 - active, 2 - temporary limited, 3 - failed
self.lkas_status = pt_cp.vl["PSCMStatus"]['LKATorqueDeliveredStatus']
- ret.steerWarning = not is_eps_status_ok(self.lkas_status, self.car_fingerprint)
+ ret.steerWarning = self.lkas_status not in [0, 1]
return ret
diff --git a/selfdrive/car/gm/gmcan.py b/selfdrive/car/gm/gmcan.py
index 23b521f55b..9dd78e4df8 100644
--- a/selfdrive/car/gm/gmcan.py
+++ b/selfdrive/car/gm/gmcan.py
@@ -28,7 +28,7 @@ def create_gas_regen_command(packer, bus, throttle, idx, acc_engaged, at_full_st
}
dat = packer.make_can_msg("ASCMGasRegenCmd", bus, values)[2]
- values["GasRegenChecksum"] = (((0xff -dat[1]) & 0xff) << 16) | \
+ values["GasRegenChecksum"] = (((0xff - dat[1]) & 0xff) << 16) | \
(((0xff - dat[2]) & 0xff) << 8) | \
((0x100 - dat[3] - idx) & 0xff)
@@ -60,7 +60,7 @@ def create_friction_brake_command(packer, bus, apply_brake, idx, near_stop, at_f
return packer.make_can_msg("EBCMFrictionBrakeCmd", bus, values)
-def create_acc_dashboard_command(packer, bus, acc_engaged, target_speed_kph, lead_car_in_sight):
+def create_acc_dashboard_command(packer, bus, acc_engaged, target_speed_kph, lead_car_in_sight, fcw):
# Not a bit shift, dash can round up based on low 4 bits.
target_speed = int(target_speed_kph * 16) & 0xfff
@@ -68,10 +68,11 @@ def create_acc_dashboard_command(packer, bus, acc_engaged, target_speed_kph, lea
"ACCAlwaysOne" : 1,
"ACCResumeButton" : 0,
"ACCSpeedSetpoint" : target_speed,
- "ACCGapLevel" : 3 * acc_engaged, # 3 "far", 0 "inactive"
+ "ACCGapLevel" : 3 * acc_engaged, # 3 "far", 0 "inactive"
"ACCCmdActive" : acc_engaged,
"ACCAlwaysOne2" : 1,
- "ACCLeadCar" : lead_car_in_sight
+ "ACCLeadCar" : lead_car_in_sight,
+ "FCWAlert": 0x3 if fcw else 0
}
return packer.make_can_msg("ASCMActiveCruiseControlStatus", bus, values)
@@ -103,8 +104,12 @@ def create_adas_accelerometer_speed_status(bus, speed_ms, idx):
dat += [(idx << 5) + (far_range_mode << 4) + (near_range_mode << 3) + (chksum >> 8), chksum & 0xff]
return make_can_msg(0x308, bytes(dat), bus)
-def create_adas_headlights_status(bus):
- return make_can_msg(0x310, b"\x42\x04", bus)
+def create_adas_headlights_status(packer, bus):
+ values = {
+ "Always42": 0x42,
+ "Always4": 0x4,
+ }
+ return packer.make_can_msg("ASCMHeadlight", bus, values)
def create_lka_icon_command(bus, active, critical, steer):
if active and steer == 1:
@@ -120,4 +125,3 @@ def create_lka_icon_command(bus, active, critical, steer):
else:
dat = b"\x00\x00\x00"
return make_can_msg(0x104c006c, dat, bus)
-
diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py
index 55dffce205..0fc3d278ce 100755
--- a/selfdrive/car/gm/interface.py
+++ b/selfdrive/car/gm/interface.py
@@ -16,13 +16,13 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 4.0
@staticmethod
- def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]):
+ def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay)
ret.carName = "gm"
- ret.safetyModel = car.CarParams.SafetyModel.gm # default to gm
+ ret.safetyModel = car.CarParams.SafetyModel.gm
ret.enableCruise = False # stock cruise control is kept off
- # GM port is considered a community feature, since it disables AEB;
+ # GM port is a community feature
# TODO: make a port that uses a car harness and it only intercepts the camera
ret.communityFeature = True
@@ -34,6 +34,7 @@ class CarInterface(CarInterfaceBase):
tire_stiffness_factor = 0.444 # not optimized yet
# Start with a baseline lateral tuning for all GM vehicles. Override tuning as needed in each model section below.
+ ret.minSteerSpeed = 7 * CV.MPH_TO_MS
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.00]]
ret.lateralTuning.pid.kf = 0.00004 # full torque for 20 deg at 80mph means 0.00007818594
@@ -47,7 +48,7 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 2.69
ret.steerRatio = 15.7
ret.steerRatioRear = 0.
- ret.centerToFront = ret.wheelbase * 0.4 # wild guess
+ ret.centerToFront = ret.wheelbase * 0.4 # wild guess
elif candidate == CAR.MALIBU:
# supports stop and go, but initial engage must be above 18mph (which include conservatism)
@@ -56,7 +57,7 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 2.83
ret.steerRatio = 15.8
ret.steerRatioRear = 0.
- ret.centerToFront = ret.wheelbase * 0.4 # wild guess
+ ret.centerToFront = ret.wheelbase * 0.4 # wild guess
elif candidate == CAR.HOLDEN_ASTRA:
ret.mass = 1363. + STD_CARGO_KG
@@ -68,20 +69,20 @@ class CarInterface(CarInterfaceBase):
ret.steerRatioRear = 0.
elif candidate == CAR.ACADIA:
- ret.minEnableSpeed = -1. # engage speed is decided by pcm
+ ret.minEnableSpeed = -1. # engage speed is decided by pcm
ret.mass = 4353. * CV.LB_TO_KG + STD_CARGO_KG
ret.wheelbase = 2.86
- ret.steerRatio = 14.4 #end to end is 13.46
+ ret.steerRatio = 14.4 # end to end is 13.46
ret.steerRatioRear = 0.
ret.centerToFront = ret.wheelbase * 0.4
elif candidate == CAR.BUICK_REGAL:
ret.minEnableSpeed = 18 * CV.MPH_TO_MS
- ret.mass = 3779. * CV.LB_TO_KG + STD_CARGO_KG # (3849+3708)/2
- ret.wheelbase = 2.83 #111.4 inches in meters
- ret.steerRatio = 14.4 # guess for tourx
+ ret.mass = 3779. * CV.LB_TO_KG + STD_CARGO_KG # (3849+3708)/2
+ ret.wheelbase = 2.83 # 111.4 inches in meters
+ ret.steerRatio = 14.4 # guess for tourx
ret.steerRatioRear = 0.
- ret.centerToFront = ret.wheelbase * 0.4 # guess for tourx
+ ret.centerToFront = ret.wheelbase * 0.4 # guess for tourx
elif candidate == CAR.CADILLAC_ATS:
ret.minEnableSpeed = 18 * CV.MPH_TO_MS
@@ -135,7 +136,7 @@ class CarInterface(CarInterfaceBase):
but = self.CS.prev_cruise_buttons
if but == CruiseButtons.RES_ACCEL:
if not (ret.cruiseState.enabled and ret.standstill):
- be.type = ButtonType.accelCruise # Suppress resume button if we're resuming from stop so we don't adjust speed.
+ be.type = ButtonType.accelCruise # Suppress resume button if we're resuming from stop so we don't adjust speed.
elif but == CruiseButtons.DECEL_SET:
be.type = ButtonType.decelCruise
elif but == CruiseButtons.CANCEL:
@@ -149,13 +150,15 @@ class CarInterface(CarInterfaceBase):
events = self.create_common_events(ret, pcm_enable=False)
if ret.vEgo < self.CP.minEnableSpeed:
- events.add(EventName.speedTooLow)
+ events.add(EventName.belowEngageSpeed)
if self.CS.park_brake:
events.add(EventName.parkBrake)
if ret.cruiseState.standstill:
events.add(EventName.resumeRequired)
if self.CS.pcm_acc_status == AccState.FAULTED:
events.add(EventName.controlsFailed)
+ if ret.vEgo < self.CP.minSteerSpeed:
+ events.add(car.CarEvent.EventName.belowSteerSpeed)
# handle button presses
for b in ret.buttonEvents:
@@ -182,9 +185,9 @@ class CarInterface(CarInterfaceBase):
# In GM, PCM faults out if ACC command overlaps user gas.
enabled = c.enabled and not self.CS.out.gasPressed
- can_sends = self.CC.update(enabled, self.CS, self.frame, \
+ can_sends = self.CC.update(enabled, self.CS, self.frame,
c.actuators,
- hud_v_cruise, c.hudControl.lanesVisible, \
+ hud_v_cruise, c.hudControl.lanesVisible,
c.hudControl.leadVisible, c.hudControl.visualAlert)
self.frame += 1
diff --git a/selfdrive/car/gm/radar_interface.py b/selfdrive/car/gm/radar_interface.py
index 8a2f9a2e69..dc2c2f7b7c 100755
--- a/selfdrive/car/gm/radar_interface.py
+++ b/selfdrive/car/gm/radar_interface.py
@@ -1,7 +1,6 @@
#!/usr/bin/env python3
from __future__ import print_function
import math
-import time
from cereal import car
from opendbc.can.parser import CANParser
from selfdrive.car.gm.values import DBC, CAR, CanBus
@@ -17,30 +16,28 @@ NUM_SLOTS = 20
LAST_RADAR_MSG = RADAR_HEADER_MSG + NUM_SLOTS
def create_radar_can_parser(car_fingerprint):
-
- dbc_f = DBC[car_fingerprint]['radar']
- if car_fingerprint in (CAR.VOLT, CAR.MALIBU, CAR.HOLDEN_ASTRA, CAR.ACADIA, CAR.CADILLAC_ATS):
- # C1A-ARS3-A by Continental
- radar_targets = list(range(SLOT_1_MSG, SLOT_1_MSG + NUM_SLOTS))
- signals = list(zip(['FLRRNumValidTargets',
- 'FLRRSnsrBlckd', 'FLRRYawRtPlsblityFlt',
- 'FLRRHWFltPrsntInt', 'FLRRAntTngFltPrsnt',
- 'FLRRAlgnFltPrsnt', 'FLRRSnstvFltPrsntInt'] +
- ['TrkRange'] * NUM_SLOTS + ['TrkRangeRate'] * NUM_SLOTS +
- ['TrkRangeAccel'] * NUM_SLOTS + ['TrkAzimuth'] * NUM_SLOTS +
- ['TrkWidth'] * NUM_SLOTS + ['TrkObjectID'] * NUM_SLOTS,
- [RADAR_HEADER_MSG] * 7 + radar_targets * 6,
- [0] * 7 +
- [0.0] * NUM_SLOTS + [0.0] * NUM_SLOTS +
- [0.0] * NUM_SLOTS + [0.0] * NUM_SLOTS +
- [0.0] * NUM_SLOTS + [0] * NUM_SLOTS))
-
- checks = []
-
- return CANParser(dbc_f, signals, checks, CanBus.OBSTACLE)
- else:
+ if car_fingerprint not in (CAR.VOLT, CAR.MALIBU, CAR.HOLDEN_ASTRA, CAR.ACADIA, CAR.CADILLAC_ATS):
return None
+ # C1A-ARS3-A by Continental
+ radar_targets = list(range(SLOT_1_MSG, SLOT_1_MSG + NUM_SLOTS))
+ signals = list(zip(['FLRRNumValidTargets',
+ 'FLRRSnsrBlckd', 'FLRRYawRtPlsblityFlt',
+ 'FLRRHWFltPrsntInt', 'FLRRAntTngFltPrsnt',
+ 'FLRRAlgnFltPrsnt', 'FLRRSnstvFltPrsntInt'] +
+ ['TrkRange'] * NUM_SLOTS + ['TrkRangeRate'] * NUM_SLOTS +
+ ['TrkRangeAccel'] * NUM_SLOTS + ['TrkAzimuth'] * NUM_SLOTS +
+ ['TrkWidth'] * NUM_SLOTS + ['TrkObjectID'] * NUM_SLOTS,
+ [RADAR_HEADER_MSG] * 7 + radar_targets * 6,
+ [0] * 7 +
+ [0.0] * NUM_SLOTS + [0.0] * NUM_SLOTS +
+ [0.0] * NUM_SLOTS + [0.0] * NUM_SLOTS +
+ [0.0] * NUM_SLOTS + [0] * NUM_SLOTS))
+
+ checks = []
+
+ return CANParser(DBC[car_fingerprint]['radar'], signals, checks, CanBus.OBSTACLE)
+
class RadarInterface(RadarInterfaceBase):
def __init__(self, CP):
super().__init__(CP)
@@ -53,8 +50,7 @@ class RadarInterface(RadarInterfaceBase):
def update(self, can_strings):
if self.rcp is None:
- time.sleep(self.radar_ts) # nothing to do
- return car.RadarData.new_message()
+ return super().update(None)
vls = self.rcp.update_strings(can_strings)
self.updated_messages.update(vls)
@@ -95,7 +91,7 @@ class RadarInterface(RadarInterfaceBase):
self.pts[targetId] = car.RadarData.RadarPoint.new_message()
self.pts[targetId].trackId = targetId
distance = cpt['TrkRange']
- self.pts[targetId].dRel = distance # from front of car
+ self.pts[targetId].dRel = distance # from front of car
# From driver's pov, left is positive
self.pts[targetId].yRel = math.sin(cpt['TrkAzimuth'] * CV.DEG_TO_RAD) * distance
self.pts[targetId].vRel = cpt['TrkRangeRate']
@@ -103,7 +99,7 @@ class RadarInterface(RadarInterfaceBase):
self.pts[targetId].yvRel = float('nan')
for oldTarget in list(self.pts.keys()):
- if not oldTarget in currentTargets:
+ if oldTarget not in currentTargets:
del self.pts[oldTarget]
ret.points = list(self.pts.values())
diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py
index 6a35c17c9b..efe696f8a6 100644
--- a/selfdrive/car/gm/values.py
+++ b/selfdrive/car/gm/values.py
@@ -1,3 +1,5 @@
+# flake8: noqa
+
from cereal import car
from selfdrive.car import dbc_dict
Ecu = car.CarParams.Ecu
@@ -11,27 +13,24 @@ class CAR:
BUICK_REGAL = "BUICK REGAL ESSENCE 2018"
class CruiseButtons:
- INIT = 0
- UNPRESS = 1
- RES_ACCEL = 2
- DECEL_SET = 3
- MAIN = 5
- CANCEL = 6
+ INIT = 0
+ UNPRESS = 1
+ RES_ACCEL = 2
+ DECEL_SET = 3
+ MAIN = 5
+ CANCEL = 6
class AccState:
- OFF = 0
- ACTIVE = 1
- FAULTED = 3
+ OFF = 0
+ ACTIVE = 1
+ FAULTED = 3
STANDSTILL = 4
class CanBus:
POWERTRAIN = 0
- OBSTACLE = 1
- CHASSIS = 2
- SW_GMLAN = 3
-
-def is_eps_status_ok(eps_status, car_fingerprint):
- return eps_status in [0, 1]
+ OBSTACLE = 1
+ CHASSIS = 2
+ SW_GMLAN = 3
FINGERPRINTS = {
# Astra BK MY17, ASCM unplugged
diff --git a/selfdrive/car/honda/carcontroller.py b/selfdrive/car/honda/carcontroller.py
index a09dffce30..0438dd76a0 100644
--- a/selfdrive/car/honda/carcontroller.py
+++ b/selfdrive/car/honda/carcontroller.py
@@ -96,8 +96,8 @@ class CarController():
self.params = CarControllerParams(CP)
- def update(self, enabled, CS, frame, actuators, \
- pcm_speed, pcm_override, pcm_cancel_cmd, pcm_accel, \
+ def update(self, enabled, CS, frame, actuators,
+ pcm_speed, pcm_override, pcm_cancel_cmd, pcm_accel,
hud_v_cruise, hud_show_lanes, hud_show_car, hud_alert):
P = self.params
diff --git a/selfdrive/car/honda/carstate.py b/selfdrive/car/honda/carstate.py
index 91124564e7..4aaa98aa66 100644
--- a/selfdrive/car/honda/carstate.py
+++ b/selfdrive/car/honda/carstate.py
@@ -20,7 +20,7 @@ def calc_cruise_offset(offset, speed):
def get_can_signals(CP):
-# this function generates lists for signal, messages and initial values
+ # this function generates lists for signal, messages and initial values
signals = [
("XMISSION_SPEED", "ENGINE_DATA", 0),
("WHEEL_SPEED_FL", "WHEEL_SPEEDS", 0),
@@ -128,10 +128,15 @@ def get_can_signals(CP):
("MAIN_ON", "SCM_BUTTONS", 0)]
elif CP.carFingerprint in (CAR.CRV, CAR.CRV_EU, CAR.ACURA_RDX, CAR.PILOT_2019, CAR.RIDGELINE):
signals += [("MAIN_ON", "SCM_BUTTONS", 0)]
- elif CP.carFingerprint in (CAR.FIT, CAR.HRV):
+ elif CP.carFingerprint == CAR.FIT:
signals += [("CAR_GAS", "GAS_PEDAL_2", 0),
("MAIN_ON", "SCM_BUTTONS", 0),
("BRAKE_HOLD_ACTIVE", "VSA_STATUS", 0)]
+ elif CP.carFingerprint == CAR.HRV:
+ signals += [("CAR_GAS", "GAS_PEDAL", 0),
+ ("MAIN_ON", "SCM_BUTTONS", 0),
+ ("BRAKE_HOLD_ACTIVE", "VSA_STATUS", 0)]
+
elif CP.carFingerprint == CAR.ODYSSEY:
signals += [("MAIN_ON", "SCM_FEEDBACK", 0),
("EPB_STATE", "EPB_STATUS", 0)]
@@ -167,7 +172,7 @@ class CarState(CarStateBase):
self.v_cruise_pcm_prev = 0
self.cruise_mode = 0
- def update(self, cp, cp_cam):
+ def update(self, cp, cp_cam, cp_body):
ret = car.CarState.new_message()
# car params
@@ -179,7 +184,8 @@ class CarState(CarStateBase):
self.prev_cruise_setting = self.cruise_setting
# ******************* parse out can *******************
- if self.CP.carFingerprint in (CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_HYBRID, CAR.INSIGHT): # TODO: find wheels moving bit in dbc
+ # TODO: find wheels moving bit in dbc
+ if self.CP.carFingerprint in (CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_HYBRID, CAR.INSIGHT):
ret.standstill = cp.vl["ENGINE_DATA"]['XMISSION_SPEED'] < 0.1
ret.doorOpen = bool(cp.vl["SCM_FEEDBACK"]['DRIVERS_DOOR_OPEN'])
elif self.CP.carFingerprint == CAR.ODYSSEY_CHN:
@@ -228,7 +234,8 @@ class CarState(CarStateBase):
ret.rightBlinker = cp.vl["SCM_FEEDBACK"]['RIGHT_BLINKER'] != 0
self.brake_hold = cp.vl["VSA_STATUS"]['BRAKE_HOLD_ACTIVE']
- if self.CP.carFingerprint in (CAR.CIVIC, CAR.ODYSSEY, CAR.CRV_5G, CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_HYBRID, CAR.INSIGHT):
+ if self.CP.carFingerprint in (CAR.CIVIC, CAR.ODYSSEY, CAR.CRV_5G, CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH,
+ CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_HYBRID, CAR.INSIGHT):
self.park_brake = cp.vl["EPB_STATUS"]['EPB_STATE'] != 0
main_on = cp.vl["SCM_FEEDBACK"]['MAIN_ON']
elif self.CP.carFingerprint == CAR.ODYSSEY_CHN:
@@ -243,7 +250,7 @@ class CarState(CarStateBase):
self.pedal_gas = cp.vl["POWERTRAIN_DATA"]['PEDAL_GAS']
# crv doesn't include cruise control
- if self.CP.carFingerprint in (CAR.CRV, CAR.CRV_EU, CAR.ODYSSEY, CAR.ACURA_RDX, CAR.RIDGELINE, CAR.PILOT_2019, CAR.ODYSSEY_CHN):
+ if self.CP.carFingerprint in (CAR.CRV, CAR.CRV_EU, CAR.HRV, CAR.ODYSSEY, CAR.ACURA_RDX, CAR.RIDGELINE, CAR.PILOT_2019, CAR.ODYSSEY_CHN):
ret.gas = self.pedal_gas / 256.
else:
ret.gas = cp.vl["GAS_PEDAL_2"]['CAR_GAS'] / 256.
@@ -252,7 +259,7 @@ class CarState(CarStateBase):
# TODO: Replace tests by toyota so this can go away
if self.CP.enableGasInterceptor:
self.user_gas = (cp.vl["GAS_SENSOR"]['INTERCEPTOR_GAS'] + cp.vl["GAS_SENSOR"]['INTERCEPTOR_GAS2']) / 2.
- self.user_gas_pressed = self.user_gas > 1e-5 # this works because interceptor read < 0 when pedal position is 0. Once calibrated, this will change
+ self.user_gas_pressed = self.user_gas > 1e-5 # this works because interceptor read < 0 when pedal position is 0. Once calibrated, this will change
ret.gasPressed = self.user_gas_pressed
else:
ret.gasPressed = self.pedal_gas > 1e-5
@@ -269,7 +276,7 @@ class CarState(CarStateBase):
ret.cruiseState.speedOffset = calc_cruise_offset(0, ret.vEgo)
if self.CP.carFingerprint in (CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.ACCORDH, CAR.CRV_HYBRID, CAR.INSIGHT):
ret.brakePressed = cp.vl["POWERTRAIN_DATA"]['BRAKE_PRESSED'] != 0 or \
- (self.brake_switch and self.brake_switch_prev and \
+ (self.brake_switch and self.brake_switch_prev and
cp.ts["POWERTRAIN_DATA"]['BRAKE_SWITCH'] != self.brake_switch_ts)
self.brake_switch_prev = self.brake_switch
self.brake_switch_ts = cp.ts["POWERTRAIN_DATA"]['BRAKE_SWITCH']
@@ -291,7 +298,8 @@ class CarState(CarStateBase):
ret.brake = cp.vl["VSA_STATUS"]['USER_BRAKE']
ret.cruiseState.enabled = cp.vl["POWERTRAIN_DATA"]['ACC_STATUS'] != 0
- ret.cruiseState.available = bool(main_on) and self.cruise_mode == 0
+ ret.cruiseState.available = bool(main_on)
+ ret.cruiseState.nonAdaptive = self.cruise_mode != 0
# Gets rid of Pedal Grinding noise when brake is pressed at slow speeds for some models
if self.CP.carFingerprint in (CAR.PILOT, CAR.PILOT_2019, CAR.RIDGELINE):
@@ -314,6 +322,12 @@ class CarState(CarStateBase):
self.stock_hud = cp_cam.vl["ACC_HUD"]
self.stock_brake = cp_cam.vl["BRAKE_COMMAND"]
+ if self.CP.carFingerprint in (CAR.CRV_5G, ):
+ # BSM messages are on B-CAN, requires a panda forwarding B-CAN messages to CAN 0
+ # more info here: https://github.com/commaai/openpilot/pull/1867
+ ret.leftBlindspot = cp_body.vl["BSM_STATUS_LEFT"]['BSM_ALERT'] == 1
+ ret.rightBlindspot = cp_body.vl["BSM_STATUS_RIGHT"]['BSM_ALERT'] == 1
+
return ret
@staticmethod
@@ -339,11 +353,24 @@ class CarState(CarStateBase):
("FCM_PROBLEM", "ACC_HUD", 0),
("ICONS", "ACC_HUD", 0)]
-
# all hondas except CRV, RDX and 2019 Odyssey@China use 0xe4 for steering
checks = [(0xe4, 100)]
if CP.carFingerprint in [CAR.CRV, CAR.CRV_EU, CAR.ACURA_RDX, CAR.ODYSSEY_CHN]:
checks = [(0x194, 100)]
- bus_cam = 1 if CP.carFingerprint in HONDA_BOSCH and not CP.isPandaBlack else 2
+ bus_cam = 1 if CP.carFingerprint in HONDA_BOSCH and not CP.isPandaBlack else 2
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, bus_cam)
+
+ @staticmethod
+ def get_body_can_parser(CP):
+ signals = []
+ checks = []
+
+ if CP.carFingerprint == CAR.CRV_5G:
+ signals += [("BSM_ALERT", "BSM_STATUS_RIGHT", 0),
+ ("BSM_ALERT", "BSM_STATUS_LEFT", 0)]
+
+ bus_body = 0 # B-CAN is forwarded to ACC-CAN radar side (CAN 0 on fake ethernet port)
+ return CANParser(DBC[CP.carFingerprint]['body'], signals, checks, bus_body)
+
+ return None
diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py
index 0edae57dd9..ac8bfe3b9f 100755
--- a/selfdrive/car/honda/interface.py
+++ b/selfdrive/car/honda/interface.py
@@ -82,12 +82,16 @@ class CarInterface(CarInterfaceBase):
else:
self.compute_gb = compute_gb_honda
+ @staticmethod
+ def compute_gb(accel, speed): # pylint: disable=method-hidden
+ raise NotImplementedError
+
@staticmethod
def calc_accel_override(a_ego, a_target, v_ego, v_target):
# normalized max accel. Allowing max accel at low speed causes speed overshoots
max_accel_bp = [10, 20] # m/s
- max_accel_v = [0.714, 1.0] # unit of max accel
+ max_accel_v = [0.714, 1.0] # unit of max accel
max_accel = interp(v_ego, max_accel_bp, max_accel_v)
# limit the pcm accel cmd if:
@@ -115,8 +119,7 @@ class CarInterface(CarInterfaceBase):
return float(max(max_accel, a_target / A_ACC_MAX)) * min(speedLimiter, accelLimiter)
@staticmethod
- def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]):
-
+ def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]): # pylint: disable=dangerous-default-value
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay)
ret.carName = "honda"
@@ -144,7 +147,7 @@ class CarInterface(CarInterfaceBase):
# For modeling details, see p.198-200 in "The Science of Vehicle Dynamics (2014), M. Guiggiani"
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0], [0]]
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kf = 0.00006 # conservative feed-forward
+ ret.lateralTuning.pid.kf = 0.00006 # conservative feed-forward
eps_modified = False
for fw in car_fw:
@@ -182,37 +185,41 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = CivicParams.WHEELBASE
ret.centerToFront = CivicParams.CENTER_TO_FRONT
ret.steerRatio = 15.38 # 10.93 is end-to-end spec
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 1.
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]]
ret.longitudinalTuning.kpBP = [0., 5., 35.]
- ret.longitudinalTuning.kpV = [3.6, 2.4, 1.5]
+ ret.longitudinalTuning.kpV = [1.2, 0.8, 0.5]
ret.longitudinalTuning.kiBP = [0., 35.]
- ret.longitudinalTuning.kiV = [0.54, 0.36]
+ ret.longitudinalTuning.kiV = [0.18, 0.12]
elif candidate in (CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH):
stop_and_go = True
- if not candidate == CAR.ACCORDH: # Hybrid uses same brake msg as hatch
+ if not candidate == CAR.ACCORDH: # Hybrid uses same brake msg as hatch
ret.safetyParam = 1 # Accord and CRV 5G use an alternate user brake msg
ret.mass = 3279. * CV.LB_TO_KG + STD_CARGO_KG
ret.wheelbase = 2.83
ret.centerToFront = ret.wheelbase * 0.39
ret.steerRatio = 16.33 # 11.82 is spec end-to-end
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 0.8467
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]]
ret.longitudinalTuning.kpBP = [0., 5., 35.]
ret.longitudinalTuning.kpV = [1.2, 0.8, 0.5]
ret.longitudinalTuning.kiBP = [0., 35.]
ret.longitudinalTuning.kiV = [0.18, 0.12]
+ if eps_modified:
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.3], [0.09]]
+ else:
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]]
+
elif candidate == CAR.ACURA_ILX:
stop_and_go = False
ret.mass = 3095. * CV.LB_TO_KG + STD_CARGO_KG
ret.wheelbase = 2.67
ret.centerToFront = ret.wheelbase * 0.37
ret.steerRatio = 18.61 # 15.3 is spec end-to-end
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]] # TODO: determine if there is a dead zone at the top end
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 0.72
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]]
ret.longitudinalTuning.kpBP = [0., 5., 35.]
@@ -226,7 +233,7 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 2.62
ret.centerToFront = ret.wheelbase * 0.41
ret.steerRatio = 16.89 # as spec
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 1000], [0, 1000]] # TODO: determine if there is a dead zone at the top end
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 1000], [0, 1000]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 0.444
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]]
ret.longitudinalTuning.kpBP = [0., 5., 35.]
@@ -259,11 +266,11 @@ class CarInterface(CarInterfaceBase):
elif candidate == CAR.CRV_HYBRID:
stop_and_go = True
ret.safetyParam = 1 # Accord and CRV 5G use an alternate user brake msg
- ret.mass = 1667. + STD_CARGO_KG # mean of 4 models in kg
+ ret.mass = 1667. + STD_CARGO_KG # mean of 4 models in kg
ret.wheelbase = 2.66
ret.centerToFront = ret.wheelbase * 0.41
ret.steerRatio = 16.0 # 12.3 is spec end-to-end
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 0.677
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]]
ret.longitudinalTuning.kpBP = [0., 5., 35.]
@@ -277,7 +284,7 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 2.53
ret.centerToFront = ret.wheelbase * 0.39
ret.steerRatio = 13.06
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 0.75
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.06]]
ret.longitudinalTuning.kpBP = [0., 5., 35.]
@@ -305,7 +312,7 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 2.68
ret.centerToFront = ret.wheelbase * 0.38
ret.steerRatio = 15.0 # as spec
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 1000], [0, 1000]] # TODO: determine if there is a dead zone at the top end
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 1000], [0, 1000]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 0.444
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]]
ret.longitudinalTuning.kpBP = [0., 5., 35.]
@@ -319,7 +326,7 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 3.00
ret.centerToFront = ret.wheelbase * 0.41
ret.steerRatio = 14.35 # as spec
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 0.82
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.45], [0.135]]
ret.longitudinalTuning.kpBP = [0., 5., 35.]
@@ -333,7 +340,7 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 2.90
ret.centerToFront = ret.wheelbase * 0.41 # from CAR.ODYSSEY
ret.steerRatio = 14.35
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 32767], [0, 32767]] # TODO: determine if there is a dead zone at the top end
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 32767], [0, 32767]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 0.82
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.45], [0.135]]
ret.longitudinalTuning.kpBP = [0., 5., 35.]
@@ -343,11 +350,11 @@ class CarInterface(CarInterfaceBase):
elif candidate in (CAR.PILOT, CAR.PILOT_2019):
stop_and_go = False
- ret.mass = 4204. * CV.LB_TO_KG + STD_CARGO_KG # average weight
+ ret.mass = 4204. * CV.LB_TO_KG + STD_CARGO_KG # average weight
ret.wheelbase = 2.82
ret.centerToFront = ret.wheelbase * 0.428
ret.steerRatio = 17.25 # as spec
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 0.444
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.38], [0.11]]
ret.longitudinalTuning.kpBP = [0., 5., 35.]
@@ -361,7 +368,7 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 3.18
ret.centerToFront = ret.wheelbase * 0.41
ret.steerRatio = 15.59 # as spec
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 0.444
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.38], [0.11]]
ret.longitudinalTuning.kpBP = [0., 5., 35.]
@@ -375,7 +382,7 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 2.7
ret.centerToFront = ret.wheelbase * 0.39
ret.steerRatio = 15.0 # 12.58 is spec end-to-end
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 0.82
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]]
ret.longitudinalTuning.kpBP = [0., 5., 35.]
@@ -383,7 +390,6 @@ class CarInterface(CarInterfaceBase):
ret.longitudinalTuning.kiBP = [0., 35.]
ret.longitudinalTuning.kiV = [0.18, 0.12]
-
else:
raise ValueError("unsupported car %s" % candidate)
@@ -402,7 +408,7 @@ class CarInterface(CarInterfaceBase):
tire_stiffness_factor=tire_stiffness_factor)
ret.gasMaxBP = [0.] # m/s
- ret.gasMaxV = [0.6] if ret.enableGasInterceptor else [0.] # max gas allowed
+ ret.gasMaxV = [0.6] if ret.enableGasInterceptor else [0.] # max gas allowed
ret.brakeMaxBP = [5., 20.] # m/s
ret.brakeMaxV = [1., 0.8] # max brake allowed
@@ -420,10 +426,12 @@ class CarInterface(CarInterfaceBase):
# ******************* do can recv *******************
self.cp.update_strings(can_strings)
self.cp_cam.update_strings(can_strings)
+ if self.cp_body:
+ self.cp_body.update_strings(can_strings)
- ret = self.CS.update(self.cp, self.cp_cam)
+ ret = self.CS.update(self.cp, self.cp_cam, self.cp_body)
- ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
+ ret.canValid = self.cp.can_valid and self.cp_cam.can_valid and (self.cp_body is None or self.cp_body.can_valid)
ret.yawRate = self.VM.yaw_rate(ret.steeringAngle * CV.DEG_TO_RAD, ret.vEgo)
# FIXME: read sendcan for brakelights
brakelights_threshold = 0.02 if self.CS.CP.carFingerprint == CAR.CIVIC else 0.1
@@ -476,12 +484,13 @@ class CarInterface(CarInterfaceBase):
events.add(EventName.parkBrake)
if self.CP.enableCruise and ret.vEgo < self.CP.minEnableSpeed:
- events.add(EventName.speedTooLow)
+ events.add(EventName.belowEngageSpeed)
# it can happen that car cruise disables while comma system is enabled: need to
# keep braking if needed or if the speed is very low
- if self.CP.enableCruise and not ret.cruiseState.enabled and (c.actuators.brake <= 0. or not self.CP.openpilotLongitudinalControl):
- # non loud alert if cruise disbales below 25mph as expected (+ a little margin)
+ if self.CP.enableCruise and not ret.cruiseState.enabled \
+ and (c.actuators.brake <= 0. or not self.CP.openpilotLongitudinalControl):
+ # non loud alert if cruise disables below 25mph as expected (+ a little margin)
if ret.vEgo < self.CP.minEnableSpeed + 2.:
events.add(EventName.speedTooLow)
else:
diff --git a/selfdrive/car/honda/radar_interface.py b/selfdrive/car/honda/radar_interface.py
index b1606e64ad..6acec73d3c 100755
--- a/selfdrive/car/honda/radar_interface.py
+++ b/selfdrive/car/honda/radar_interface.py
@@ -1,12 +1,10 @@
#!/usr/bin/env python3
-import os
-import time
from cereal import car
from opendbc.can.parser import CANParser
from selfdrive.car.interfaces import RadarInterfaceBase
+from selfdrive.car.honda.values import DBC
-def _create_nidec_can_parser():
- dbc_f = 'acura_ilx_2016_nidec.dbc'
+def _create_nidec_can_parser(car_fingerprint):
radar_messages = [0x400] + list(range(0x430, 0x43A)) + list(range(0x440, 0x446))
signals = list(zip(['RADAR_STATE'] +
['LONG_DIST'] * 16 + ['NEW_TRACK'] * 16 + ['LAT_DIST'] * 16 +
@@ -14,8 +12,7 @@ def _create_nidec_can_parser():
[0x400] + radar_messages[1:] * 4,
[0] + [255] * 16 + [1] * 16 + [0] * 16 + [0] * 16))
checks = list(zip([0x445], [20]))
- fn = os.path.splitext(dbc_f)[0].encode('utf8')
- return CANParser(fn, signals, checks, 1)
+ return CANParser(DBC[car_fingerprint]['radar'], signals, checks, 1)
class RadarInterface(RadarInterfaceBase):
@@ -30,7 +27,10 @@ class RadarInterface(RadarInterfaceBase):
self.delay = int(round(0.1 / CP.radarTimeStep)) # 0.1s delay of radar
# Nidec
- self.rcp = _create_nidec_can_parser()
+ if self.radar_off_can:
+ self.rcp = None
+ else:
+ self.rcp = _create_nidec_can_parser(CP.carFingerprint)
self.trigger_msg = 0x445
self.updated_messages = set()
@@ -38,9 +38,7 @@ class RadarInterface(RadarInterfaceBase):
# in Bosch radar and we are only steering for now, so sleep 0.05s to keep
# radard at 20Hz and return no points
if self.radar_off_can:
- if 'NO_RADAR_SLEEP' not in os.environ:
- time.sleep(self.radar_ts)
- return car.RadarData.new_message()
+ return super().update(None)
vls = self.rcp.update_strings(can_strings)
self.updated_messages.update(vls)
@@ -52,7 +50,6 @@ class RadarInterface(RadarInterfaceBase):
self.updated_messages.clear()
return rr
-
def _update(self, updated_messages):
ret = car.RadarData.new_message()
diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py
index 05db8c023b..713c38ae1b 100644
--- a/selfdrive/car/honda/values.py
+++ b/selfdrive/car/honda/values.py
@@ -1,3 +1,5 @@
+# flake8: noqa
+
from cereal import car
from selfdrive.car import dbc_dict
@@ -6,10 +8,10 @@ VisualAlert = car.CarControl.HUDControl.VisualAlert
# Car button codes
class CruiseButtons:
- RES_ACCEL = 4
- DECEL_SET = 3
- CANCEL = 2
- MAIN = 1
+ RES_ACCEL = 4
+ DECEL_SET = 3
+ CANCEL = 2
+ MAIN = 1
# See dbc files for info on values"
VISUAL_HUD = {
@@ -126,7 +128,7 @@ FINGERPRINTS = {
},
# 2019 Ridgeline
{
- 57: 3, 145: 8, 228: 5, 229: 4, 308: 5, 316: 8, 339: 7, 342: 6, 344: 8, 380: 8, 392: 6, 399: 7, 419: 8, 420: 8, 422:8, 425: 8, 426: 8, 427: 3, 432: 7, 464: 8, 476: 4, 490: 8, 512: 6, 513: 6, 545: 5, 546: 3, 597: 8, 660: 8, 773: 7, 777: 8, 795: 8, 800: 8, 804: 8, 808: 8, 819: 7, 821: 5, 871: 8, 882: 2, 884: 7, 892: 8, 923: 2, 929: 8, 963: 8, 965: 8, 966: 8, 967: 8, 983: 8, 985: 3, 1027: 5, 1029: 8, 1036: 8, 1039: 8, 1064: 7, 1088: 8, 1089: 8, 1092: 1, 1108: 8, 1125: 8, 1296: 8, 1365: 5, 424: 5, 1613: 5, 1616: 5, 1618: 5, 1623: 5, 1668: 5
+ 57: 3, 145: 8, 228: 5, 229: 4, 308: 5, 316: 8, 339: 7, 342: 6, 344: 8, 380: 8, 392: 6, 399: 7, 419: 8, 420: 8, 422: 8, 425: 8, 426: 8, 427: 3, 432: 7, 464: 8, 476: 4, 490: 8, 512: 6, 513: 6, 545: 5, 546: 3, 597: 8, 660: 8, 773: 7, 777: 8, 795: 8, 800: 8, 804: 8, 808: 8, 819: 7, 821: 5, 871: 8, 882: 2, 884: 7, 892: 8, 923: 2, 929: 8, 963: 8, 965: 8, 966: 8, 967: 8, 983: 8, 985: 3, 1027: 5, 1029: 8, 1036: 8, 1039: 8, 1064: 7, 1088: 8, 1089: 8, 1092: 1, 1108: 8, 1125: 8, 1296: 8, 1365: 5, 424: 5, 1613: 5, 1616: 5, 1618: 5, 1623: 5, 1668: 5
}],
# 2019 Insight
CAR.INSIGHT: [{
@@ -149,8 +151,10 @@ FW_VERSIONS = {
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
b'37805-6A0-A640\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-M520\x00\x00',
],
(Ecu.shiftByWire, 0x18da0bf1, None): [
@@ -158,16 +162,23 @@ FW_VERSIONS = {
],
(Ecu.transmission, 0x18da1ef1, None): [
b'28102-6B8-A560\x00\x00',
+ b'28102-6B8-A570\x00\x00',
+ b'28102-6B8-A800\x00\x00',
+ b'28102-6B8-C570\x00\x00',
b'28102-6B8-M520\x00\x00',
],
(Ecu.electricBrakeBooster, 0x18da2bf1, None): [
b'46114-TVA-A060\x00\x00',
b'46114-TVA-A080\x00\x00',
+ b'46114-TVA-A120\x00\x00',
],
(Ecu.vsa, 0x18da28f1, None): [
+ b'57114-TVA-C040\x00\x00',
b'57114-TVA-C050\x00\x00',
+ b'57114-TVA-C060\x00\x00',
],
(Ecu.eps, 0x18da30f1, None): [
+ b'39990-TVA,A150\x00\x00',
b'39990-TVA-A150\x00\x00',
b'39990-TVA-A160\x00\x00',
b'39990-TVA-X030\x00\x00',
@@ -182,15 +193,16 @@ FW_VERSIONS = {
(Ecu.combinationMeter, 0x18da60f1, None): [
b'78109-TVA-A210\x00\x00',
b'78109-TVC-A010\x00\x00',
+ b'78109-TVC-A020\x00\x00',
b'78109-TVC-A110\x00\x00',
b'78109-TVC-A210\x00\x00',
+ b'78109-TVC-C110\x00\x00',
b'78109-TVC-M510\x00\x00',
],
(Ecu.hud, 0x18da61f1, None): [
b'78209-TVA-A010\x00\x00',
],
(Ecu.fwdRadar, 0x18dab0f1, None): [
- b'36802-TVA-A160\x00\x00',
b'36802-TVA-A160\x00\x00',
b'36802-TVA-A170\x00\x00',
b'36802-TWA-A070\x00\x00',
@@ -206,15 +218,21 @@ FW_VERSIONS = {
CAR.ACCORD_15: {
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
b'37805-6A0-9620\x00\x00',
+ b'37805-6A0-A540\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-C540\x00\x00',
b'37805-6A1-H650\x00\x00',
],
(Ecu.transmission, 0x18da1ef1, None): [
b'28101-6A7-A220\x00\x00',
+ b'28101-6A7-A230\x00\x00',
b'28101-6A7-A320\x00\x00',
+ b'28101-6A7-A330\x00\x00',
b'28101-6A7-A510\x00\x00',
b'28101-6A9-H140\x00\x00',
],
@@ -224,16 +242,19 @@ FW_VERSIONS = {
(Ecu.electricBrakeBooster, 0x18da2bf1, None): [
b'46114-TVA-A050\x00\x00',
b'46114-TVA-A060\x00\x00',
+ b'46114-TVA-A080\x00\x00',
b'46114-TVA-A120\x00\x00',
b'46114-TVE-H550\x00\x00',
],
(Ecu.combinationMeter, 0x18da60f1, None): [
b'78109-TVA-A010\x00\x00',
+ b'78109-TVA-A110\x00\x00',
b'78109-TVA-A210\x00\x00',
b'78109-TVA-A220\x00\x00',
b'78109-TVA-A310\x00\x00',
- b'78109-TWA-A210\x00\x00',
+ b'78109-TVA-C010\x00\x00',
b'78109-TVE-H610\x00\x00',
+ b'78109-TWA-A210\x00\x00',
],
(Ecu.hud, 0x18da61f1, None): [
b'78209-TVA-A010\x00\x00',
@@ -270,15 +291,19 @@ FW_VERSIONS = {
],
(Ecu.vsa, 0x18da28f1, None): [
b'57114-TWA-A040\x00\x00',
+ b'57114-TWA-A050\x00\x00',
],
(Ecu.srs, 0x18da53f1, None): [
b'77959-TWA-A440\x00\x00',
],
(Ecu.combinationMeter, 0x18da60f1, None): [
b'78109-TWA-A010\x00\x00',
+ b'78109-TWA-A020\x00\x00',
+ b'78109-TWA-A110\x00\x00',
b'78109-TWA-A120\x00\x00',
b'78109-TWA-A210\x00\x00',
- b'78109-TWA-A110\x00\x00',
+ b'78109-TWA-A220\x00\x00',
+
],
(Ecu.shiftByWire, 0x18da0bf1, None): [
b'54008-TWA-A910\x00\x00',
@@ -305,10 +330,20 @@ FW_VERSIONS = {
b'37805-5AA-A670\x00\x00',
b'37805-5AA-A680\x00\x00',
b'37805-5AA-A810\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-5AJ-A610\x00\x00',
+ b'37805-5AJ-A620\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-A960\x00\x00',
+ b'37805-5BA-L930\x00\x00',
b'37805-5BA-L940\x00\x00',
b'37805-5BA-L960\x00\x00',
],
@@ -324,6 +359,7 @@ FW_VERSIONS = {
b'28101-5DJ-A510\x00\x00',
],
(Ecu.vsa, 0x18da28f1, None): [
+ b'57114-TBA-A540\x00\x00',
b'57114-TBA-A550\x00\x00',
b'57114-TBA-A560\x00\x00',
b'57114-TBA-A570\x00\x00',
@@ -340,20 +376,28 @@ FW_VERSIONS = {
b'77959-TBG-A030\x00\x00',
],
(Ecu.combinationMeter, 0x18da60f1, None): [
+ b'78109-TBA-A510\x00\x00',
+ b'78109-TBA-A520\x00\x00',
+ b'78109-TBA-A530\x00\x00',
b'78109-TBC-A310\x00\x00',
b'78109-TBC-A320\x00\x00',
b'78109-TBC-A510\x00\x00',
b'78109-TBC-A520\x00\x00',
b'78109-TBC-A530\x00\x00',
+ b'78109-TBC-C510\x00\x00',
+ b'78109-TBC-C520\x00\x00',
b'78109-TBC-C530\x00\x00',
b'78109-TBH-A530\x00\x00',
b'78109-TEG-A310\x00\x00',
],
(Ecu.fwdCamera, 0x18dab0f1, None): [
+ b'36161-TBA-A020\x00\x00',
b'36161-TBA-A030\x00\x00',
+ b'36161-TBA-A040\x00\x00',
b'36161-TBC-A020\x00\x00',
b'36161-TBC-A030\x00\x00',
b'36161-TEG-A010\x00\x00',
+ b'36161-TEG-A020\x00\x00',
],
(Ecu.gateway, 0x18daeff1, None): [
b'38897-TBA-A010\x00\x00',
@@ -362,24 +406,40 @@ FW_VERSIONS = {
},
CAR.CIVIC_BOSCH: {
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
+ b'37805-5AA-A940\x00\x00',
b'37805-5AA-A950\x00\x00',
+ b'37805-5AA-L940\x00\x00',
b'37805-5AA-L950\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-AK20\x00\x00',
+ b'37805-5AN-AR20\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-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-L540\x00\x00',
b'37805-5BB-L640\x00\x00',
],
(Ecu.transmission, 0x18da1ef1, None): [
b'28101-5CG-A920\x00\x00',
+ b'28101-5CG-AB10\x00\x00',
+ b'28101-5CG-C110\x00\x00',
b'28101-5CG-C220\x00\x00',
b'28101-5CG-C320\x00\x00',
b'28101-5CG-G020\x00\x00',
@@ -388,14 +448,19 @@ FW_VERSIONS = {
b'28101-5CK-A150\x00\x00',
b'28101-5CK-C130\x00\x00',
b'28101-5CK-C140\x00\x00',
+ b'28101-5DJ-A610\x00\x00',
b'28101-5DJ-A710\x00\x00',
b'28101-5DV-E330\x00\x00',
],
(Ecu.vsa, 0x18da28f1, None): [
b'57114-TBG-A340\x00\x00',
+ b'57114-TBG-A350\x00\x00',
b'57114-TGG-A340\x00\x00',
- b'57114-TGL-G330\x00\x00',
b'57114-TGG-C320\x00\x00',
+ b'57114-TGG-L320\x00\x00',
+ b'57114-TGG-L330\x00\x00',
+ b'57114-TGL-G330\x00\x00',
+
],
(Ecu.eps, 0x18da30f1, None): [
b'39990-TBA-C020\x00\x00',
@@ -404,22 +469,28 @@ FW_VERSIONS = {
b'39990-TGG-A020\x00\x00',
b'39990-TGG-A120\x00\x00',
b'39990-TGL-E130\x00\x00',
- b'39990-TGG-A020\x00\x00',
],
(Ecu.srs, 0x18da53f1, None): [
b'77959-TBA-A060\x00\x00',
b'77959-TEA-G020\x00\x00',
b'77959-TGG-A020\x00\x00',
+ b'77959-TGG-A030\x00\x00',
b'77959-TGG-G010\x00\x00',
],
(Ecu.combinationMeter, 0x18da60f1, None): [
+ b'78109-TBA-A110\x00\x00',
b'78109-TBA-A910\x00\x00',
+ b'78109-TBA-C340\x00\x00',
+ b'78109-TBA-C910\x00\x00',
b'78109-TBC-A740\x00\x00',
b'78109-TFJ-G020\x00\x00',
b'78109-TGG-A210\x00\x00',
b'78109-TGG-A220\x00\x00',
b'78109-TGG-A310\x00\x00',
b'78109-TGG-A320\x00\x00',
+ b'78109-TGG-A330\x00\x00',
+ b'78109-TGG-A610\x00\x00',
+ b'78109-TGG-A620\x00\x00',
b'78109-TGG-A810\x00\x00',
b'78109-TGG-A820\x00\x00',
b'78109-TGL-G120\x00\x00',
@@ -428,19 +499,18 @@ FW_VERSIONS = {
b'36802-TBA-A150\x00\x00',
b'36802-TFJ-G060\x00\x00',
b'36802-TGG-A050\x00\x00',
- b'36802-TGL-G040\x00\x00',
b'36802-TGG-A060\x00\x00',
+ b'36802-TGG-A130\x00\x00',
+ b'36802-TGL-G040\x00\x00',
],
(Ecu.fwdCamera, 0x18dab5f1, None): [
b'36161-TBA-A130\x00\x00',
+ b'36161-TBA-A140\x00\x00',
b'36161-TFJ-G070\x00\x00',
b'36161-TGG-A060\x00\x00',
- b'36161-TGL-G050\x00\x00',
b'36161-TGG-A080\x00\x00',
- ],
- (Ecu.unknown, 0x18daeff1, None): [
- b'38897-TBA-A110\x00\x00',
- b'38897-TBA-A020\x00\x00',
+ b'36161-TGG-A120\x00\x00',
+ b'36161-TGL-G050\x00\x00',
],
(Ecu.gateway, 0x18daeff1, None): [
b'38897-TBA-A110\x00\x00',
@@ -459,19 +529,29 @@ FW_VERSIONS = {
(Ecu.fwdCamera, 0x18dab5f1, None): [b'36161-TFK-G130\x00\x00'],
(Ecu.gateway, 0x18daeff1, None): [b'38897-TBA-A020\x00\x00'],
},
+ CAR.CRV: {
+ (Ecu.vsa, 0x18da28f1, None): [b'57114-T1W-A230\x00\x00',],
+ (Ecu.srs, 0x18da53f1, None): [b'77959-T0A-A230\x00\x00',],
+ (Ecu.combinationMeter, 0x18da60f1, None): [b'78109-T1W-A210\x00\x00',],
+ (Ecu.fwdRadar, 0x18dab0f1, None): [b'36161-T1W-A830\x00\x00',],
+ },
CAR.CRV_5G: {
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
+ b'37805-5PA-3060\x00\x00',
b'37805-5PA-3080\x00\x00',
b'37805-5PA-4050\x00\x00',
+ b'37805-5PA-6520\x00\x00',
b'37805-5PA-6530\x00\x00',
b'37805-5PA-6630\x00\x00',
+ b'37805-5PA-9640\x00\x00',
+ b'37805-5PA-9830\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-9640\x00\x00',
b'37805-5PD-Q630\x00\x00',
],
(Ecu.transmission, 0x18da1ef1, None): [
@@ -480,9 +560,11 @@ FW_VERSIONS = {
b'28101-5RG-A040\x00\x00',
b'28101-5RG-A120\x00\x00',
b'28101-5RG-A220\x00\x00',
+ b'28101-5RH-A020\x00\x00',
b'28101-5RH-A030\x00\x00',
b'28101-5RH-A040\x00\x00',
b'28101-5RH-A120\x00\x00',
+ b'28101-5RH-A220\x00\x00',
b'28101-5RL-Q010\x00\x00',
],
(Ecu.vsa, 0x18da28f1, None): [
@@ -495,6 +577,7 @@ FW_VERSIONS = {
(Ecu.eps, 0x18da30f1, None): [
b'39990-TLA,A040\x00\x00',
b'39990-TLA-A040\x00\x00',
+ b'39990-TLA-A110\x00\x00',
b'39990-TLA-A220\x00\x00',
b'39990-TMT-T010\x00\x00',
],
@@ -511,6 +594,7 @@ FW_VERSIONS = {
b'78109-TLA-C210\x00\x00',
b'78109-TLB-A110\x00\x00',
b'78109-TLB-A210\x00\x00',
+ b'78109-TLB-A220\x00\x00',
b'78109-TMC-Q210\x00\x00',
],
(Ecu.gateway, 0x18daeff1, None): [
@@ -540,41 +624,81 @@ FW_VERSIONS = {
],
},
CAR.CRV_EU: {
- (Ecu.programmedFuelInjection, 0x18da10f1, None): [b'37805-R5Z-G740\x00\x00'],
+ (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'],
(Ecu.fwdRadar, 0x18dab0f1, None): [b'36161-T1V-G520\x00\x00'],
(Ecu.shiftByWire, 0x18da0bf1, None): [b'54008-T1V-G010\x00\x00'],
- (Ecu.transmission, 0x18da1ef1, None): [b'28101-5LH-E120\x00\x00'],
- (Ecu.combinationMeter, 0x18da60f1, None): [b'78109-T1V-G020\x00\x00'],
+ (Ecu.transmission, 0x18da1ef1, None): [
+ b'28101-5LH-E120\x00\x00',
+ b'28103-5LH-E100\x00\x00',
+ ],
+ (Ecu.combinationMeter, 0x18da60f1, None): [
+ b'78109-T1V-G020\x00\x00',
+ b'78109-T1B-3050\x00\x00',
+ ],
(Ecu.srs, 0x18da53f1, None): [b'77959-T1G-G940\x00\x00'],
},
CAR.CRV_HYBRID: {
(Ecu.vsa, 0x18da28f1, None): [
b'57114-TPA-G020\x00\x00',
+ b'57114-TPG-A020\x00\x00',
],
(Ecu.eps, 0x18da30f1, None): [
b'39990-TPA-G030\x00\x00',
+ b'39990-TPG-A020\x00\x00',
],
(Ecu.gateway, 0x18daeff1, None): [
b'38897-TMA-H110\x00\x00',
+ b'38897-TPG-A110\x00\x00',
],
(Ecu.shiftByWire, 0x18da0bf1, None): [
b'54008-TMB-H510\x00\x00',
+ b'54008-TMB-H610\x00\x00',
],
(Ecu.fwdCamera, 0x18dab5f1, None): [
b'36161-TPA-E050\x00\x00',
+ b'36161-TPG-A030\x00\x00',
],
(Ecu.combinationMeter, 0x18da60f1, None): [
b'78109-TPA-G520\x00\x00',
+ b'78109-TPG-A110\x00\x00',
],
(Ecu.hud, 0x18da61f1, None): [
b'78209-TLA-X010\x00\x00',
],
(Ecu.fwdRadar, 0x18dab0f1, None): [
b'36802-TPA-E040\x00\x00',
+ b'36802-TPG-A020\x00\x00',
],
(Ecu.srs, 0x18da53f1, None): [
b'77959-TLA-G220\x00\x00',
+ b'77959-TLA-C320\x00\x00',
+ ],
+ },
+ CAR.FIT: {
+ (Ecu.vsa, 0x18da28f1, None): [
+ b'57114-T5R-L220\x00\x00',
+ ],
+ (Ecu.eps, 0x18da30f1, None): [
+ b'39990-T5R-C020\x00\x00',
+ b'39990-T5R-C030\x00\x00',
+ ],
+ (Ecu.gateway, 0x18daeff1, None): [
+ b'38897-T5A-J010\x00\x00',
+ ],
+ (Ecu.combinationMeter, 0x18da60f1, None): [
+ b'78109-T5A-A420\x00\x00',
+ b'78109-T5A-A910\x00\x00',
+ ],
+ (Ecu.fwdRadar, 0x18dab0f1, None): [
+ b'36161-T5R-A240\x00\x00',
+ b'36161-T5R-A520\x00\x00',
+ ],
+ (Ecu.srs, 0x18da53f1, None): [
+ b'77959-T5R-A230\x00\x00',
],
},
CAR.ODYSSEY: {
@@ -601,13 +725,16 @@ FW_VERSIONS = {
b'36161-THR-A030\x00\x00',
b'36161-THR-A110\x00\x00',
b'36161-THR-A720\x00\x00',
+ b'36161-THR-A730\x00\x00',
b'36161-THR-A810\x00\x00',
+ b'36161-THR-A910\x00\x00',
b'36161-THR-C010\x00\x00',
],
(Ecu.transmission, 0x18da1ef1, None): [
b'28101-5NZ-A310\x00\x00',
b'28101-5NZ-C310\x00\x00',
b'28102-5MX-A001\x00\x00',
+ b'28102-5MX-A600\x00\x00',
b'28102-5MX-A610\x00\x00',
b'28102-5MX-A710\x00\x00',
b'28102-5MX-A900\x00\x00',
@@ -623,12 +750,15 @@ FW_VERSIONS = {
b'78109-THR-A230\x00\x00',
b'78109-THR-A430\x00\x00',
b'78109-THR-A820\x00\x00',
+ b'78109-THR-A830\x00\x00',
b'78109-THR-AB20\x00\x00',
- b'78109-THR-AB20\x00\x00',
+ b'78109-THR-AB30\x00\x00',
b'78109-THR-AB40\x00\x00',
b'78109-THR-AC40\x00\x00',
+ b'78109-THR-AE20\x00\x00',
b'78109-THR-AE40\x00\x00',
b'78109-THR-AL10\x00\x00',
+ b'78109-THR-AN10\x00\x00',
b'78109-THR-C330\x00\x00',
b'78109-THR-CE20\x00\x00',
],
@@ -636,14 +766,58 @@ FW_VERSIONS = {
b'54008-THR-A020\x00\x00',
],
},
+ CAR.PILOT: {
+ (Ecu.shiftByWire, 0x18da0bf1, None): [
+ b'54008-TG7-A520\x00\x00',
+ ],
+ (Ecu.transmission, 0x18da1ef1, None): [
+ b'28101-5EZ-A210\x00\x00',
+ b'28101-5EZ-A100\x00\x00',
+ b'28101-5EZ-A060\x00\x00',
+ b'28101-5EZ-A050\x00\x00',
+ ],
+ (Ecu.programmedFuelInjection, 0x18da10f1, None): [
+ b'37805-RLV-C910\x00\x00',
+ b'37805-RLV-C520\x00\x00',
+ b'37805-RLV-C510\x00\x00',
+ b'37805-RLV-4070\x00\x00',
+ b'37805-RLV-A830\x00\x00',
+ ],
+ (Ecu.eps, 0x18da30f1, None): [
+ b'39990-TG7-A040\x00\x00',
+ b'39990-TG7-A030\x00\x00',
+ ],
+ (Ecu.fwdCamera, 0x18dab0f1, None): [
+ b'36161-TG7-A520\x00\x00',
+ b'36161-TG7-A820\x00\x00',
+ b'36161-TG7-A720\x00\x00',
+ ],
+ (Ecu.srs, 0x18da53f1, None): [
+ b'77959-TG7-A110\x00\x00',
+ b'77959-TG7-A020\x00\x00',
+ ],
+ (Ecu.combinationMeter, 0x18da60f1, None): [
+ b'78109-TG7-A720\x00\x00',
+ b'78109-TG7-A520\x00\x00',
+ b'78109-TG7-A420\x00\x00',
+ b'78109-TG7-A040\x00\x00',
+ ],
+ (Ecu.vsa, 0x18da28f1, None): [
+ b'57114-TG7-A140\x00\x00',
+ b'57114-TG7-A240\x00\x00',
+ b'57114-TG7-A230\x00\x00',
+ ],
+
+ },
CAR.PILOT_2019: {
(Ecu.eps, 0x18da30f1, None): [
b'39990-TG7-A060\x00\x00',
b'39990-TGS-A230\x00\x00',
],
(Ecu.gateway, 0x18daeff1, None): [
- b'38897-TG7-A110\x00\x00',
b'38897-TG7-A030\x00\x00',
+ b'38897-TG7-A110\x00\x00',
+ b'38897-TG7-A210\x00\x00',
],
(Ecu.fwdCamera, 0x18dab0f1, None): [
b'36161-TG7-A630\x00\x00',
@@ -658,6 +832,8 @@ FW_VERSIONS = {
],
(Ecu.combinationMeter, 0x18da60f1, None): [
b'78109-TG7-AJ20\x00\x00',
+ b'78109-TG7-AK10\x00\x00',
+ b'78109-TG7-AK20\x00\x00',
b'78109-TG7-AP10\x00\x00',
b'78109-TG7-AP20\x00\x00',
b'78109-TG8-AJ20\x00\x00',
@@ -679,6 +855,7 @@ FW_VERSIONS = {
b'39990-T6Z-A030\x00\x00',
],
(Ecu.fwdCamera, 0x18dab0f1, None): [
+ b'36161-T6Z-A020\x00\x00',
b'36161-T6Z-A310\x00\x00',
b'36161-T6Z-A520\x00\x00',
],
@@ -694,6 +871,7 @@ FW_VERSIONS = {
b'77959-T6Z-A020\x00\x00',
],
(Ecu.vsa, 0x18da28f1, None): [
+ b'57114-T6Z-A120\x00\x00',
b'57114-T6Z-A130\x00\x00',
b'57114-T6Z-A520\x00\x00',
],
@@ -707,10 +885,23 @@ FW_VERSIONS = {
],
(Ecu.fwdCamera, 0x18dab5f1, None): [
b'36161-TXM-A050\x00\x00',
+ b'36161-TXM-A060\x00\x00',
],
(Ecu.srs, 0x18da53f1, None): [
b'77959-TXM-A230\x00\x00',
],
+ (Ecu.vsa, 0x18da28f1, None): [
+ b'57114-TXM-A040\x00\x00',
+ ],
+ (Ecu.shiftByWire, 0x18da0bf1, None): [
+ b'54008-TWA-A910\x00\x00',
+ ],
+ (Ecu.gateway, 0x18daeff1, None): [
+ b'38897-TXM-A020\x00\x00',
+ ],
+ (Ecu.combinationMeter, 0x18da60f1, None): [
+ b'78109-TXM-A020\x00\x00',
+ ],
},
CAR.HRV: {
(Ecu.gateway, 0x18daeff1, None): [b'38897-T7A-A010\x00\x00'],
@@ -731,7 +922,7 @@ DBC = {
CAR.CIVIC_BOSCH: dbc_dict('honda_civic_hatchback_ex_2017_can_generated', None),
CAR.CIVIC_BOSCH_DIESEL: dbc_dict('honda_civic_sedan_16_diesel_2019_can_generated', None),
CAR.CRV: dbc_dict('honda_crv_touring_2016_can_generated', 'acura_ilx_2016_nidec'),
- CAR.CRV_5G: dbc_dict('honda_crv_ex_2017_can_generated', None),
+ CAR.CRV_5G: dbc_dict('honda_crv_ex_2017_can_generated', None, body_dbc='honda_crv_ex_2017_body_generated'),
CAR.CRV_EU: dbc_dict('honda_crv_executive_2016_can_generated', 'acura_ilx_2016_nidec'),
CAR.CRV_HYBRID: dbc_dict('honda_crv_hybrid_2019_can_generated', None),
CAR.FIT: dbc_dict('honda_fit_ex_2018_can_generated', 'acura_ilx_2016_nidec'),
@@ -796,4 +987,4 @@ ECU_FINGERPRINT = {
Ecu.fwdCamera: [0xE4, 0x194], # steer torque cmd
}
-HONDA_BOSCH = [CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_5G, CAR.CRV_HYBRID, CAR.INSIGHT]
+HONDA_BOSCH = set([CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_5G, CAR.CRV_HYBRID, CAR.INSIGHT])
diff --git a/selfdrive/car/hyundai/carcontroller.py b/selfdrive/car/hyundai/carcontroller.py
index 59fef40d20..787cc91b00 100644
--- a/selfdrive/car/hyundai/carcontroller.py
+++ b/selfdrive/car/hyundai/carcontroller.py
@@ -1,4 +1,5 @@
from cereal import car
+from common.realtime import DT_CTRL
from selfdrive.car import apply_std_steer_torque_limits
from selfdrive.car.hyundai.hyundaican import create_lkas11, create_clu11, create_lfa_mfa
from selfdrive.car.hyundai.values import Buttons, SteerLimitParams, CAR
@@ -13,7 +14,7 @@ def process_hud_alert(enabled, fingerprint, visual_alert, left_lane,
# initialize to no line visible
sys_state = 1
- if left_lane and right_lane or sys_warning: #HUD alert only display when LKAS status is active
+ if left_lane and right_lane or sys_warning: # HUD alert only display when LKAS status is active
if enabled or sys_warning:
sys_state = 3
else:
@@ -40,9 +41,7 @@ class CarController():
self.car_fingerprint = CP.carFingerprint
self.packer = CANPacker(dbc_name)
self.steer_rate_limited = False
- self.resume_cnt = 0
self.last_resume_frame = 0
- self.last_lead_distance = 0
def update(self, enabled, CS, frame, actuators, pcm_cancel_cmd, visual_alert,
left_lane, right_lane, left_lane_depart, right_lane_depart):
@@ -56,7 +55,7 @@ class CarController():
# fix for Genesis hard fault at low speed
if CS.out.vEgo < 16.7 and self.car_fingerprint == CAR.HYUNDAI_GENESIS:
- lkas_active = 0
+ lkas_active = False
if not lkas_active:
apply_steer = 0
@@ -75,28 +74,15 @@ class CarController():
if pcm_cancel_cmd:
can_sends.append(create_clu11(self.packer, frame, CS.clu11, Buttons.CANCEL))
-
elif CS.out.cruiseState.standstill:
- # run only first time when the car stopped
- if self.last_lead_distance == 0:
- # get the lead distance from the Radar
- self.last_lead_distance = CS.lead_distance
- self.resume_cnt = 0
- # when lead car starts moving, create 6 RES msgs
- elif CS.lead_distance != self.last_lead_distance and (frame - self.last_resume_frame) > 5:
+ # SCC won't resume anyway when the lead distace is less than 3.7m
+ # send resume at a max freq of 5Hz
+ if CS.lead_distance > 3.7 and (frame - self.last_resume_frame)*DT_CTRL > 0.2:
can_sends.append(create_clu11(self.packer, frame, CS.clu11, Buttons.RES_ACCEL))
- self.resume_cnt += 1
- # interval after 6 msgs
- if self.resume_cnt > 5:
- self.last_resume_frame = frame
- self.clu11_cnt = 0
- # reset lead distnce after the car starts moving
- elif self.last_lead_distance != 0:
- self.last_lead_distance = 0
-
+ self.last_resume_frame = frame
# 20 Hz LFA MFA message
- if frame % 5 == 0 and self.car_fingerprint in [CAR.SONATA, CAR.PALISADE]:
+ if frame % 5 == 0 and self.car_fingerprint in [CAR.SONATA, CAR.PALISADE, CAR.IONIQ]:
can_sends.append(create_lfa_mfa(self.packer, frame, enabled))
return can_sends
diff --git a/selfdrive/car/hyundai/carstate.py b/selfdrive/car/hyundai/carstate.py
index d6f7d30ec5..61d9de05bb 100644
--- a/selfdrive/car/hyundai/carstate.py
+++ b/selfdrive/car/hyundai/carstate.py
@@ -1,5 +1,5 @@
from cereal import car
-from selfdrive.car.hyundai.values import DBC, STEER_THRESHOLD, FEATURES
+from selfdrive.car.hyundai.values import DBC, STEER_THRESHOLD, FEATURES, EV_HYBRID
from selfdrive.car.interfaces import CarStateBase
from opendbc.can.parser import CANParser
from selfdrive.config import Conversions as CV
@@ -11,7 +11,7 @@ class CarState(CarStateBase):
def update(self, cp, cp_cam):
ret = car.CarState.new_message()
- ret.doorOpen = any([cp.vl["CGW1"]['CF_Gway_DrvDrSw'],cp.vl["CGW1"]['CF_Gway_AstDrSw'],
+ ret.doorOpen = any([cp.vl["CGW1"]['CF_Gway_DrvDrSw'], cp.vl["CGW1"]['CF_Gway_AstDrSw'],
cp.vl["CGW2"]['CF_Gway_RLDrSw'], cp.vl["CGW2"]['CF_Gway_RRDrSw']])
ret.seatbeltUnlatched = cp.vl["CGW1"]['CF_Gway_DrvSeatBeltSw'] == 0
@@ -41,8 +41,7 @@ class CarState(CarStateBase):
ret.cruiseState.standstill = cp.vl["SCC11"]['SCCInfoDisplay'] == 4.
if ret.cruiseState.enabled:
- is_set_speed_in_mph = int(cp.vl["CLU11"]["CF_Clu_SPEED_UNIT"])
- speed_conv = CV.MPH_TO_MS if is_set_speed_in_mph else CV.KPH_TO_MS
+ speed_conv = CV.MPH_TO_MS if cp.vl["CLU11"]["CF_Clu_SPEED_UNIT"] else CV.KPH_TO_MS
ret.cruiseState.speed = cp.vl["SCC11"]['VSetDis'] * speed_conv
else:
ret.cruiseState.speed = 0
@@ -54,12 +53,16 @@ class CarState(CarStateBase):
# TODO: Check this
ret.brakeLights = bool(cp.vl["TCS13"]['BrakeLight'] or ret.brakePressed)
- #TODO: find pedal signal for EV/HYBRID Cars
- ret.gas = cp.vl["EMS12"]['PV_AV_CAN'] / 100
- ret.gasPressed = bool(cp.vl["EMS16"]["CF_Ems_AclAct"])
+ if self.CP.carFingerprint in EV_HYBRID:
+ ret.gas = cp.vl["E_EMS11"]['Accel_Pedal_Pos'] / 256.
+ ret.gasPressed = ret.gas > 0
+ else:
+ ret.gas = cp.vl["EMS12"]['PV_AV_CAN'] / 100
+ ret.gasPressed = bool(cp.vl["EMS16"]["CF_Ems_AclAct"])
# TODO: refactor gear parsing in function
- # Gear Selection via Cluster - For those Kia/Hyundai which are not fully discovered, we can use the Cluster Indicator for Gear Selection, as this seems to be standard over all cars, but is not the preferred method.
+ # Gear Selection via Cluster - For those Kia/Hyundai which are not fully discovered, we can use the Cluster Indicator for Gear Selection,
+ # as this seems to be standard over all cars, but is not the preferred method.
if self.CP.carFingerprint in FEATURES["use_cluster_gears"]:
if cp.vl["CLU15"]["CF_Clu_InhibitD"] == 1:
ret.gearShifter = GearShifter.drive
@@ -85,7 +88,7 @@ class CarState(CarStateBase):
# Gear Selecton - This is only compatible with optima hybrid 2017
elif self.CP.carFingerprint in FEATURES["use_elect_gears"]:
gear = cp.vl["ELECT_GEAR"]["Elect_Gear_Shifter"]
- if gear in (5, 8): # 5: D, 8: sport mode
+ if gear in (5, 8): # 5: D, 8: sport mode
ret.gearShifter = GearShifter.drive
elif gear == 6:
ret.gearShifter = GearShifter.neutral
@@ -98,7 +101,7 @@ class CarState(CarStateBase):
# Gear Selecton - This is not compatible with all Kia/Hyundai's, But is the best way for those it is compatible with
else:
gear = cp.vl["LVR12"]["CF_Lvr_Gear"]
- if gear in (5, 8): # 5: D, 8: sport mode
+ if gear in (5, 8): # 5: D, 8: sport mode
ret.gearShifter = GearShifter.drive
elif gear == 6:
ret.gearShifter = GearShifter.neutral
@@ -109,11 +112,22 @@ class CarState(CarStateBase):
else:
ret.gearShifter = GearShifter.unknown
+ if self.CP.carFingerprint in FEATURES["use_fca"]:
+ ret.stockAeb = cp.vl["FCA11"]['FCA_CmdAct'] != 0
+ ret.stockFcw = cp.vl["FCA11"]['CF_VSM_Warn'] == 2
+ else:
+ ret.stockAeb = cp.vl["SCC12"]['AEB_CmdAct'] != 0
+ ret.stockFcw = cp.vl["SCC12"]['CF_VSM_Warn'] == 2
+
+ if self.CP.carFingerprint in FEATURES["use_bsm"]:
+ ret.leftBlindspot = cp.vl["LCA11"]["CF_Lca_IndLeft"] != 0
+ ret.rightBlindspot = cp.vl["LCA11"]["CF_Lca_IndRight"] != 0
+
# save the entire LKAS11 and CLU11
self.lkas11 = cp_cam.vl["LKAS11"]
self.clu11 = cp.vl["CLU11"]
self.park_brake = cp.vl["CGW1"]['CF_Gway_ParkBrakeSw']
- self.steer_state = cp.vl["MDPS12"]['CF_Mdps_ToiActive'] #0 NOT ACTIVE, 1 ACTIVE
+ self.steer_state = cp.vl["MDPS12"]['CF_Mdps_ToiActive'] # 0 NOT ACTIVE, 1 ACTIVE
self.lead_distance = cp.vl["SCC11"]['ACC_ObjDist']
return ret
@@ -163,7 +177,7 @@ class CarState(CarStateBase):
("ESC_Off_Step", "TCS15", 0),
- ("CF_Lvr_GearInf", "LVR11", 0), #Transmission Gear (0 = N or P, 1-8 = Fwd, 14 = Rev)
+ ("CF_Lvr_GearInf", "LVR11", 0), # Transmission Gear (0 = N or P, 1-8 = Fwd, 14 = Rev)
("CR_Mdps_StrColTq", "MDPS12", 0),
("CF_Mdps_ToiActive", "MDPS12", 0),
@@ -179,9 +193,6 @@ class CarState(CarStateBase):
("SCCInfoDisplay", "SCC11", 0),
("ACC_ObjDist", "SCC11", 0),
("ACCMode", "SCC12", 1),
-
- ("PV_AV_CAN", "EMS12", 0),
- ("CF_Ems_AclAct", "EMS16", 0),
]
checks = [
@@ -197,9 +208,32 @@ class CarState(CarStateBase):
("SAS11", 100),
("SCC11", 50),
("SCC12", 50),
- ("EMS12", 100),
- ("EMS16", 100),
]
+
+ if CP.carFingerprint in FEATURES["use_bsm"]:
+ signals += [
+ ("CF_Lca_IndLeft", "LCA11", 0),
+ ("CF_Lca_IndRight", "LCA11", 0),
+ ]
+ checks += [("LCA11", 50)]
+
+ if CP.carFingerprint in EV_HYBRID:
+ signals += [
+ ("Accel_Pedal_Pos", "E_EMS11", 0),
+ ]
+ checks += [
+ ("E_EMS11", 50),
+ ]
+ else:
+ signals += [
+ ("PV_AV_CAN", "EMS12", 0),
+ ("CF_Ems_AclAct", "EMS16", 0),
+ ]
+ checks += [
+ ("EMS12", 100),
+ ("EMS16", 100),
+ ]
+
if CP.carFingerprint in FEATURES["use_cluster_gears"]:
signals += [
("CF_Clu_InhibitD", "CLU15", 0),
@@ -212,7 +246,7 @@ class CarState(CarStateBase):
]
elif CP.carFingerprint in FEATURES["use_tcu_gears"]:
signals += [
- ("CUR_GR", "TCU12",0)
+ ("CUR_GR", "TCU12", 0)
]
checks += [
("TCU12", 100)
@@ -222,12 +256,24 @@ class CarState(CarStateBase):
checks += [("ELECT_GEAR", 20)]
else:
signals += [
- ("CF_Lvr_Gear","LVR12",0)
+ ("CF_Lvr_Gear", "LVR12", 0)
]
checks += [
("LVR12", 100)
]
+ if CP.carFingerprint in FEATURES["use_fca"]:
+ signals += [
+ ("FCA_CmdAct", "FCA11", 0),
+ ("CF_VSM_Warn", "FCA11", 0),
+ ]
+ checks += [("FCA11", 50)]
+ else:
+ signals += [
+ ("AEB_CmdAct", "SCC12", 0),
+ ("CF_VSM_Warn", "SCC12", 0),
+ ]
+
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 0)
@staticmethod
@@ -235,7 +281,7 @@ class CarState(CarStateBase):
signals = [
# sig_name, sig_address, default
- ("CF_Lkas_Bca_R", "LKAS11", 0),
+ ("CF_Lkas_LdwsActivemode", "LKAS11", 0),
("CF_Lkas_LdwsSysState", "LKAS11", 0),
("CF_Lkas_SysWarning", "LKAS11", 0),
("CF_Lkas_LdwsLHWarning", "LKAS11", 0),
@@ -252,6 +298,8 @@ class CarState(CarStateBase):
("CF_Lkas_LdwsOpt_USM", "LKAS11", 0)
]
- checks = []
+ checks = [
+ ("LKAS11", 100)
+ ]
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2)
diff --git a/selfdrive/car/hyundai/hyundaican.py b/selfdrive/car/hyundai/hyundaican.py
index b5969d018b..1e7b751018 100644
--- a/selfdrive/car/hyundai/hyundaican.py
+++ b/selfdrive/car/hyundai/hyundaican.py
@@ -20,7 +20,7 @@ def create_lkas11(packer, frame, car_fingerprint, apply_steer, steer_req,
values["CF_Lkas_Chksum"] = 0
if car_fingerprint in [CAR.SONATA, CAR.PALISADE]:
- values["CF_Lkas_Bca_R"] = int(left_lane) + (int(right_lane) << 1)
+ values["CF_Lkas_LdwsActivemode"] = int(left_lane) + (int(right_lane) << 1)
values["CF_Lkas_LdwsOpt_USM"] = 2
# FcwOpt_USM 5 = Orange blinking car + lanes
@@ -40,9 +40,9 @@ def create_lkas11(packer, frame, car_fingerprint, apply_steer, steer_req,
elif car_fingerprint == CAR.HYUNDAI_GENESIS:
# This field is actually LdwsActivemode
# Genesis and Optima fault when forwarding while engaged
- values["CF_Lkas_Bca_R"] = 2
+ values["CF_Lkas_LdwsActivemode"] = 2
elif car_fingerprint == CAR.KIA_OPTIMA:
- values["CF_Lkas_Bca_R"] = 0
+ values["CF_Lkas_LdwsActivemode"] = 0
dat = packer.make_can_msg("LKAS11", 0, values)[2]
diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py
index 183ab7eed1..553d48a2b5 100644
--- a/selfdrive/car/hyundai/interface.py
+++ b/selfdrive/car/hyundai/interface.py
@@ -12,15 +12,15 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 3.0
@staticmethod
- def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]):
+ def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]): # pylint: disable=dangerous-default-value
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay)
ret.carName = "hyundai"
ret.safetyModel = car.CarParams.SafetyModel.hyundai
ret.radarOffCan = True
- # Hyundai port is a community feature for now
- ret.communityFeature = True
+ # Most Hyundai car ports are community features for now
+ ret.communityFeature = candidate not in [CAR.SONATA]
ret.steerActuatorDelay = 0.1 # Default delay
ret.steerRateCost = 0.5
@@ -41,6 +41,14 @@ class CarInterface(CarInterfaceBase):
ret.mass = 1513. + STD_CARGO_KG
ret.wheelbase = 2.84
ret.steerRatio = 13.27 * 1.15 # 15% higher at the center seems reasonable
+ tire_stiffness_factor = 0.65
+ ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
+ elif candidate == CAR.SONATA_2019:
+ ret.lateralTuning.pid.kf = 0.00005
+ ret.mass = 4497. * CV.LB_TO_KG
+ ret.wheelbase = 2.804
+ ret.steerRatio = 13.27 * 1.15 # 15% higher at the center seems reasonable
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
elif candidate == CAR.PALISADE:
@@ -74,6 +82,13 @@ class CarInterface(CarInterfaceBase):
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.16], [0.01]]
ret.minSteerSpeed = 60 * CV.KPH_TO_MS
+ elif candidate == CAR.GENESIS_G70:
+ ret.lateralTuning.pid.kf = 0.00005
+ ret.mass = 1640. + STD_CARGO_KG
+ ret.wheelbase = 2.84
+ ret.steerRatio = 16.5
+ ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.16], [0.01]]
elif candidate == CAR.GENESIS_G80:
ret.lateralTuning.pid.kf = 0.00005
ret.mass = 2060. + STD_CARGO_KG
@@ -103,31 +118,22 @@ class CarInterface(CarInterfaceBase):
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
elif candidate == CAR.KONA:
- ret.lateralTuning.pid.kf = 0.00006
- ret.mass = 1275. + STD_CARGO_KG
- ret.wheelbase = 2.7
- ret.steerRatio = 13.73 #Spec
- tire_stiffness_factor = 0.385
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
- elif candidate == CAR.IONIQ:
- ret.lateralTuning.pid.kf = 0.00006
+ ret.lateralTuning.pid.kf = 0.00005
ret.mass = 1275. + STD_CARGO_KG
ret.wheelbase = 2.7
- ret.steerRatio = 13.73 #Spec
+ ret.steerRatio = 13.73 * 1.15 # Spec
tire_stiffness_factor = 0.385
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
- ret.minSteerSpeed = 32 * CV.MPH_TO_MS
elif candidate == CAR.KONA_EV:
ret.lateralTuning.pid.kf = 0.00006
ret.mass = 1685. + STD_CARGO_KG
ret.wheelbase = 2.7
- ret.steerRatio = 13.73 #Spec
+ ret.steerRatio = 13.73 # Spec
tire_stiffness_factor = 0.385
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
- elif candidate == CAR.IONIQ_EV_LTD:
+ elif candidate in [CAR.IONIQ, CAR.IONIQ_EV_LTD]:
ret.lateralTuning.pid.kf = 0.00006
ret.mass = 1490. + STD_CARGO_KG #weight per hyundai site https://www.hyundaiusa.com/ioniq-electric/specifications.aspx
ret.wheelbase = 2.7
@@ -144,6 +150,19 @@ class CarInterface(CarInterfaceBase):
tire_stiffness_factor = 0.5
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
+ elif candidate == CAR.VELOSTER:
+ ret.lateralTuning.pid.kf = 0.00005
+ ret.mass = 3558. * CV.LB_TO_KG
+ ret.wheelbase = 2.80
+ ret.steerRatio = 13.75 * 1.15
+ tire_stiffness_factor = 0.5
+ ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
+
+ # these cars require a special panda safety mode due to missing counters and checksums in the messages
+ if candidate in [CAR.HYUNDAI_GENESIS, CAR.IONIQ_EV_LTD, CAR.IONIQ, CAR.KONA_EV, CAR.KIA_SORENTO, CAR.SONATA_2019,
+ CAR.KIA_OPTIMA, CAR.VELOSTER, CAR.KIA_STINGER, CAR.GENESIS_G70]:
+ ret.safetyModel = car.CarParams.SafetyModel.hyundaiLegacy
ret.centerToFront = ret.wheelbase * 0.4
@@ -167,9 +186,6 @@ class CarInterface(CarInterfaceBase):
ret = self.CS.update(self.cp, self.cp_cam)
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
- # TODO: button presses
- ret.buttonEvents = []
-
events = self.create_common_events(ret)
#TODO: addd abs(self.CS.angle_steers) > 90 to 'steerTempUnavailable' event
diff --git a/selfdrive/car/hyundai/radar_interface.py b/selfdrive/car/hyundai/radar_interface.py
index b5bdcd8363..fdbe837af6 100644
--- a/selfdrive/car/hyundai/radar_interface.py
+++ b/selfdrive/car/hyundai/radar_interface.py
@@ -1,6 +1,4 @@
#!/usr/bin/env python3
-import os
-import time
from cereal import car
from opendbc.can.parser import CANParser
from selfdrive.car.interfaces import RadarInterfaceBase
@@ -33,10 +31,7 @@ class RadarInterface(RadarInterfaceBase):
def update(self, can_strings):
if self.radar_off_can:
- if 'NO_RADAR_SLEEP' not in os.environ:
- time.sleep(0.05) # radard runs on RI updates
-
- return car.RadarData.new_message()
+ return super().update(None)
vls = self.rcp.update_strings(can_strings)
self.updated_messages.update(vls)
diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py
index 480ed6f269..9a39cb8f31 100644
--- a/selfdrive/car/hyundai/values.py
+++ b/selfdrive/car/hyundai/values.py
@@ -1,3 +1,5 @@
+# flake8: noqa
+
from cereal import car
from selfdrive.car import dbc_dict
Ecu = car.CarParams.Ecu
@@ -15,22 +17,24 @@ class SteerLimitParams:
class CAR:
ELANTRA = "HYUNDAI ELANTRA LIMITED ULTIMATE 2017"
ELANTRA_GT_I30 = "HYUNDAI I30 N LINE 2019 & GT 2018 DCT"
+ GENESIS_G70 = "GENESIS G70 2018"
GENESIS_G80 = "GENESIS G80 2017"
GENESIS_G90 = "GENESIS G90 2017"
HYUNDAI_GENESIS = "HYUNDAI GENESIS 2015-2016"
- IONIQ = "HYUNDAI IONIQ HYBRID PREMIUM 2017"
+ IONIQ = "HYUNDAI IONIQ ELECTRIC PREMIUM SE 2020"
IONIQ_EV_LTD = "HYUNDAI IONIQ ELECTRIC LIMITED 2019"
KIA_FORTE = "KIA FORTE E 2018"
KIA_OPTIMA = "KIA OPTIMA SX 2019 & 2016"
KIA_OPTIMA_H = "KIA OPTIMA HYBRID 2017 & SPORTS 2019"
KIA_SORENTO = "KIA SORENTO GT LINE 2018"
KIA_STINGER = "KIA STINGER GT2 2018"
- KONA = "HYUNDAI KONA 2019"
+ KONA = "HYUNDAI KONA 2020"
KONA_EV = "HYUNDAI KONA ELECTRIC 2019"
SANTA_FE = "HYUNDAI SANTA FE LIMITED 2019"
- SANTA_FE_1 = "HYUNDAI SANTA FE has no scc"
SONATA = "HYUNDAI SONATA 2020"
+ SONATA_2019 = "HYUNDAI SONATA 2019"
PALISADE = "HYUNDAI PALISADE 2020"
+ VELOSTER = "HYUNDAI VELOSTER 2019"
class Buttons:
@@ -77,21 +81,22 @@ FINGERPRINTS = {
67: 8, 68: 8, 80: 4, 160: 8, 161: 8, 272: 8, 288: 4, 339: 8, 356: 8, 357: 8, 399: 8, 544: 8, 608: 8, 672: 8, 688: 5, 704: 1, 790: 8, 809: 8, 848: 8, 880: 8, 898: 8, 900: 8, 901: 8, 904: 8, 1056: 8, 1064: 8, 1065: 8, 1072: 8, 1075: 8, 1087: 8, 1088: 8, 1151: 8, 1200: 8, 1201: 8, 1232: 4, 1264: 8, 1265: 8, 1266: 8, 1296: 8, 1306: 8, 1312: 8, 1322: 8, 1331: 8, 1332: 8, 1333: 8, 1348: 8, 1349: 8, 1369: 8, 1370: 8, 1371: 8, 1407: 8, 1415: 8, 1419: 8, 1440: 8, 1442: 4, 1461: 8, 1470: 8
}],
CAR.SONATA: [
- {67: 8, 68: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 544: 8, 545: 8, 546: 8, 547: 8, 548: 8, 549: 8, 550: 8, 576: 8, 593: 8, 608: 8, 688: 6, 809: 8, 832: 8, 854: 8, 865: 8, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 905: 8, 908: 8, 909: 8, 912: 7, 913: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1078: 4, 1089: 5, 1107: 5, 1108: 8, 1114: 8, 1136: 8, 1145: 8, 1151: 8, 1155: 8, 1156: 8, 1157: 4, 1162: 8, 1164: 8, 1168: 8, 1170: 8, 1173: 8, 1180: 8, 1183: 8, 1184: 8, 1186: 2, 1191: 2, 1193: 8, 1210: 8, 1225: 8, 1227: 8, 1265: 4, 1268: 8, 1280: 8, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1330: 8, 1339: 8, 1342: 6, 1343: 8, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1371: 8, 1378: 8, 1384: 8, 1394: 8, 1407: 8, 1419: 8, 1427: 6, 1446: 8, 1456: 4, 1460: 8, 1470: 8, 1485: 8, 1504: 3},
+ {67: 8, 68: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 544: 8, 576: 8, 593: 8, 608: 8, 688: 6, 809: 8, 832: 8, 854: 8, 865: 8, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 905: 8, 908: 8, 909: 8, 912: 7, 913: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1078: 4, 1089: 5, 1096: 8, 1107: 5, 1108: 8, 1114: 8, 1136: 8, 1145: 8, 1151: 8, 1155: 8, 1156: 8, 1157: 4, 1162: 8, 1164: 8, 1168: 8, 1170: 8, 1173: 8, 1180: 8, 1183: 8, 1184: 8, 1186: 2, 1191: 2, 1193: 8, 1210: 8, 1225: 8, 1227: 8, 1265: 4, 1268: 8, 1280: 8, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1330: 8, 1339: 8, 1342: 6, 1343: 8, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1371: 8, 1378: 8, 1379: 8, 1384: 8, 1394: 8, 1407: 8, 1419: 8, 1427: 6, 1446: 8, 1456: 4, 1460: 8, 1470: 8, 1485: 8, 1504: 3, 1988: 8, 1996: 8, 2000: 8, 2004: 8, 2008: 8, 2012: 8, 2015: 8},
],
- CAR.KIA_OPTIMA: [
- {
- 64: 8, 66: 8, 67: 8, 68: 8, 127: 8, 273: 8, 274: 8, 275: 8, 339: 8, 356: 4, 399: 8, 447: 8, 512: 6, 544: 8, 593: 8, 608: 8, 688: 5, 790: 8, 809: 8, 832: 8, 884: 8, 897: 8, 899: 8, 902: 8, 903: 6, 909: 8, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1151: 6, 1168: 7, 1170: 8, 1186: 2, 1191: 2, 1253: 8, 1254: 8, 1255: 8, 1265: 4, 1280: 1, 1282: 4, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1331: 8, 1332: 8, 1333: 8, 1342: 6, 1345: 8, 1348: 8, 1349: 8, 1351: 8, 1353: 8, 1363: 8, 1365: 8, 1366: 8, 1367: 8, 1369: 8, 1407: 8, 1414: 3, 1415: 8, 1419: 8, 1425: 2, 1427: 6, 1440: 8, 1456: 4, 1470: 8, 1472: 8, 1486: 8, 1487: 8, 1491: 8, 1530: 8, 1532: 5, 1952: 8, 1960: 8, 1988: 8, 1996: 8, 2001: 8, 2004: 8, 2008: 8, 2009: 8, 2012: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8
- },
- {
- 64: 8, 66: 8, 67: 8, 68: 8, 127: 8, 128: 8, 129: 8, 273: 8, 274: 8, 275: 8, 339: 8, 354: 3, 356: 4, 399: 8, 512: 6, 544: 8, 593: 8, 608: 8, 688: 5, 790: 8, 809: 8, 832: 8, 897: 8, 899: 8, 902: 8, 903: 6, 912: 7, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1151: 6, 1168: 7, 1170: 8, 1265: 4, 1268: 8, 1280: 1, 1282: 4, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1331: 8, 1332: 8, 1333: 8, 1342: 6, 1345: 8, 1348: 8, 1349: 8, 1351: 8, 1353: 8, 1356: 8, 1363: 8, 1365: 8, 1366: 8, 1367: 8, 1369: 8, 1407: 8, 1419: 8, 1425: 2, 1427: 6, 1440: 8, 1456: 4, 1470: 8, 1472: 8, 1491: 8, 1492: 8
- },
+ CAR.SONATA_2019: [
+ {66: 8, 67: 8, 68: 8, 127: 8, 273: 8, 274: 8, 275: 8, 339: 8, 356: 4, 399: 8, 447: 8, 512: 6, 544: 8, 593: 8, 608: 8, 688: 5, 790: 8, 809: 8, 832: 8, 884: 8, 897: 8, 899: 8, 902: 8, 903: 6, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1151: 6, 1168: 7, 1170: 8, 1253: 8, 1254: 8, 1255: 8, 1265: 4, 1280: 1, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1314: 8, 1322: 8, 1331: 8, 1332: 8, 1333: 8, 1342: 6, 1345: 8, 1348: 8, 1349: 8, 1351: 8, 1353: 8, 1363: 8, 1365: 8, 1366: 8, 1367: 8, 1369: 8, 1397: 8, 1407: 8, 1415: 8, 1419: 8, 1425: 2, 1427: 6, 1440: 8, 1456: 4, 1470: 8, 1472: 8, 1486: 8, 1487: 8, 1491: 8, 1530: 8, 1532: 5, 2000: 8, 2001: 8, 2004: 8, 2005: 8, 2008: 8, 2009: 8, 2012: 8, 2013: 8, 2014: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8},
],
+ CAR.KIA_OPTIMA: [{
+ 64: 8, 66: 8, 67: 8, 68: 8, 127: 8, 128: 8, 129: 8, 273: 8, 274: 8, 275: 8, 339: 8, 354: 3, 356: 4, 399: 8, 447: 8, 512: 6, 544: 8, 558: 8, 593: 8, 608: 8, 640: 8, 688: 5, 790: 8, 809: 8, 832: 8, 884: 8, 897: 8, 899: 8, 902: 8, 903: 6, 909: 8, 912: 7, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1151: 6, 1168: 7, 1170: 8, 1186: 2, 1191: 2, 1253: 8, 1254: 8, 1255: 8, 1265: 4, 1268: 8, 1280: 1, 1282: 4, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1331: 8, 1332: 8, 1333: 8, 1342: 6, 1345: 8, 1348: 8, 1349: 8, 1351: 8, 1353: 8, 1356: 8, 1363: 8, 1365: 8, 1366: 8, 1367: 8, 1369: 8, 1407: 8, 1414: 3, 1415: 8, 1419: 8, 1425: 2, 1427: 6, 1440: 8, 1456: 4, 1470: 8, 1472: 8, 1486: 8, 1487: 8, 1491: 8, 1492: 8, 1530: 8, 1532: 5, 1792: 8, 1872: 8, 1937: 8, 1953: 8, 1968: 8, 1988: 8, 1996: 8, 2000: 8, 2001: 8, 2004: 8, 2008: 8, 2009: 8, 2012: 8, 2015: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8
+ }],
CAR.KIA_SORENTO: [{
67: 8, 68: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 544: 8, 593: 8, 608: 8, 688: 5, 809: 8, 832: 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1064: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1168: 7, 1170: 8, 1173: 8, 1265: 4, 1280: 1, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1331: 8, 1332: 8, 1333: 8, 1342: 6, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1370: 8, 1371: 8, 1384: 8, 1407: 8, 1411: 8, 1419: 8, 1425: 2, 1427: 6, 1444: 8, 1456: 4, 1470: 8, 1489: 1
}],
CAR.KIA_STINGER: [{
- 67: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 358: 6, 359: 8, 544: 8, 576: 8, 593: 8, 608: 8, 688: 5, 809: 8, 832: 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 909: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1064: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1168: 7, 1170: 8, 1173: 8, 1184: 8, 1265: 4, 1280: 1, 1281: 4, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1378: 4, 1379: 8, 1384: 8, 1407: 8, 1419: 8, 1425: 2, 1427: 6, 1456: 4, 1470: 8
+ 67: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 358: 6, 359: 8, 544: 8, 576: 8, 593: 8, 608: 8, 688: 5, 809: 8, 832: 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 909: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1064: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1168: 7, 1170: 8, 1173: 8, 1184: 8, 1265: 4, 1280: 1, 1281: 4, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1371: 8, 1378: 4, 1379: 8, 1384: 8, 1407: 8, 1419: 8, 1425: 2, 1427: 6, 1456: 4, 1470: 8
+ }],
+ CAR.GENESIS_G70: [{
+ 67: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 358: 6, 544: 8, 576: 8, 593: 8, 608: 8, 688: 5, 809: 8, 832:8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 909: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1064: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1156: 8, 1168: 7, 1170: 8, 1173:8, 1184: 8, 1186: 2, 1191: 2, 1265: 4, 1280: 1, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1379: 8, 1384: 8, 1407: 8, 1419:8, 1427: 6, 1456: 4, 1470: 8, 1988: 8, 1996: 8, 2000: 8, 2004: 8, 2008: 8, 2012: 8, 2015: 8
}],
CAR.GENESIS_G80: [{
67: 8, 68: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 358: 6, 544: 8, 593: 8, 608: 8, 688: 5, 809: 8, 832: 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 916: 8, 1024: 2, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1156: 8, 1168: 7, 1170: 8, 1173: 8, 1184: 8, 1191: 2, 1265: 4, 1280: 1, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 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
@@ -105,14 +110,17 @@ 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.IONIQ: [{
- 68: 8, 127: 8, 304: 8, 320: 8, 339: 8, 352: 8, 356: 4, 544: 8, 576: 8, 593: 8, 688: 5, 881: 8, 882: 8, 897: 8, 902: 8, 903: 8, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1136: 6, 1173: 8, 1225: 8, 1265: 4, 1280: 1, 1287: 4, 1290: 8, 1291: 8, 1292: 8, 1294: 8, 1322: 8, 1345: 8, 1348: 8, 1355: 8, 1363: 8, 1369: 8, 1407: 8, 1419: 8, 1427: 6, 1429: 8, 1430: 8, 1448: 8, 1456: 4, 1470:8, 1476: 8, 1535: 8
- }],
CAR.IONIQ_EV_LTD: [{
127: 8, 304: 8, 320: 8, 339: 8, 352: 8, 356: 4, 544: 7, 593: 8, 688: 5, 832: 8, 881: 8, 882: 8, 897: 8, 902: 8, 903: 8, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1136: 8, 1151: 6, 1168: 7, 1173: 8, 1265: 4, 1280: 1, 1287: 4, 1290: 8, 1291: 8, 1292: 8, 1294: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1355: 8, 1363: 8, 1369: 8, 1407: 8, 1419: 8, 1425: 2, 1426: 8, 1427: 6, 1429: 8, 1430: 8, 1456: 4, 1470: 8, 1507: 8, 1535: 8
}],
+ CAR.IONIQ: [{
+ 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
+ },
+ {
+ 68:8, 127: 8, 304: 8, 320: 8, 339: 8, 352: 8, 356: 4, 524: 8, 544: 8, 576: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: 6, 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, 1448: 8, 1456: 4, 1470: 8, 1473: 8, 1476: 8, 1507: 8, 1535: 8, 1988: 8, 1996: 8, 2000: 8, 2004: 8, 2005: 8, 2008: 8, 2012: 8, 2013: 8
+ }],
CAR.KONA: [{
- 67: 8, 127: 8, 304: 8, 320: 8, 339: 8, 354: 3, 356: 4, 544: 8, 593: 8, 608: 8, 688: 5, 809: 8, 832: 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 909: 8, 916: 8, 1040: 8, 1078: 4, 1107: 5, 1136: 8, 1156: 8, 1170: 8, 1173: 8, 1191: 2, 1265: 4, 1280: 1, 1287: 4, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1384: 8, 1394: 8,1407: 8, 1414: 3, 1419: 8, 1427: 6, 1456: 4, 1470: 8, 2004: 8, 2009: 8, 2012: 8
+ 67: 8, 127: 8, 304: 8, 320: 8, 339: 8, 354: 3, 356: 4, 544: 8, 593: 8, 608: 8, 688: 5, 809: 8, 832 : 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1064: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1156: 8, 1170: 8, 1173: 8, 1186: 2, 1191: 2, 1193: 8, 1265: 4,1280: 1, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1378: 8, 1384: 8, 1394: 8, 1407: 8, 1414: 3, 1419: 8, 1427: 6, 1456: 4, 1470: 8, 1988: 8, 1996: 8, 2000: 8, 2001: 8, 2004: 8, 2008: 8, 2009: 8, 2012: 8
}],
CAR.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
@@ -127,33 +135,152 @@ FINGERPRINTS = {
68: 8, 127: 8, 304: 8, 320: 8, 339: 8, 352: 8, 356: 4, 544: 8, 576: 8, 593: 8, 688: 5, 881: 8, 882: 8, 897: 8, 902: 8, 903: 8, 909: 8, 912: 7, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1136: 6, 1151: 6, 1168: 7, 1173: 8, 1180: 8, 1186: 2, 1191: 2, 1265: 4, 1268: 8, 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, 1371: 8, 1407: 8, 1419: 8, 1420: 8, 1425: 2, 1427: 6, 1429: 8, 1430: 8, 1448: 8, 1456: 4, 1470: 8, 1476: 8, 1535: 8
}],
CAR.PALISADE: [{
- 67: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 544: 8, 549: 8, 576: 8, 593: 8, 608: 8, 688: 6, 809: 8, 832: 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 905: 8, 909: 8, 913: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1064: 8, 1078: 4, 1107: 5, 1123: 8, 1136: 8, 1151: 6, 1155: 8, 1156: 8, 1157: 4, 1162: 8, 1164: 8, 1168: 7, 1170: 8, 1173: 8, 1180: 8, 1186: 2, 1191: 2, 1193: 8, 1210: 8, 1225: 8, 1227: 8, 1265: 4, 1280: 8, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1371: 8, 1378: 8, 1384: 8, 1407: 8, 1419: 8, 1427: 6, 1456: 4, 1470: 8, 2000: 8, 2005: 8, 2008: 8
+ 67: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 544: 8, 549: 8, 576: 8, 593: 8, 608: 8, 688: 6, 809: 8, 832: 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 905: 8, 909: 8, 913: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1064: 8, 1078: 4, 1107: 5, 1123: 8, 1136: 8, 1151: 6, 1155: 8, 1156: 8, 1157: 4, 1162: 8, 1164: 8, 1168: 7, 1170: 8, 1173: 8, 1180: 8, 1186: 2, 1191: 2, 1193: 8, 1210: 8, 1225: 8, 1227: 8, 1265: 4, 1280: 8, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1371: 8, 1378: 8, 1384: 8, 1407: 8, 1419: 8, 1427: 6, 1456: 4, 1470: 8, 2000: 8, 2004: 8, 2005: 8, 2008: 8, 2012: 8
}],
+ CAR.VELOSTER: [{
+ 64: 8, 66: 8, 67: 8, 68: 8, 127: 8, 128: 8, 129: 8, 273: 8, 274: 8, 275: 8, 339: 8, 354: 3, 356: 4, 399: 8, 512: 6, 544: 8, 558: 8, 593: 8, 608: 8, 688: 5, 790: 8, 809: 8, 832: 8, 884: 8, 897: 8, 899: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1170: 8, 1181: 5, 1186: 2, 1191: 2, 1265: 4, 1280: 1, 1282: 4, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1349: 8, 1351: 8, 1353: 8, 1356: 8, 1363: 8, 1365: 8, 1366: 8, 1367: 8, 1369: 8, 1378: 4, 1407: 8, 1414: 3, 1415: 8, 1419: 8, 1427: 6, 1440: 8, 1456: 4, 1470: 8, 1486: 8, 1487: 8, 1491: 8, 1530: 8, 1532: 5, 1872: 8, 1988: 8, 1996: 8, 2000: 8, 2001: 8, 2004: 8, 2008: 8, 2009: 8, 2012: 8, 2015: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8
+ }]
}
ECU_FINGERPRINT = {
Ecu.fwdCamera: [832, 1156, 1191, 1342]
}
+# Don't use these fingerprints for fingerprinting, they are still used for ECU detection
+IGNORED_FINGERPRINTS = [CAR.VELOSTER, CAR.GENESIS_G70, CAR.KONA]
+
+FW_VERSIONS = {
+ CAR.SONATA: {
+ (Ecu.fwdRadar, 0x7d0, None): [
+ b'\xf1\x00DN8_ SCC FHCUP 1.00 1.00 99110-L0000 ',
+ b'\xf1\x00DN8_ SCC F-CU- 1.00 1.00 99110-L0000 ',
+ ],
+ (Ecu.esp, 0x7d1, None): [
+ b'\xf1\x8758910-L0100\xf1\x00DN ESC \x06 104\x19\x08\x01 58910-L0100\xf1\xa01.04',
+ ],
+ (Ecu.engine, 0x7e0, None): [
+ b'\xf1\x87391162M003\xf1\xa0000F',
+ ],
+ (Ecu.eps, 0x7d4, None): [
+ b'\xf1\x8756310L0010\x00\xf1\x00DN8 MDPS C 1.00 1.01 56310L0010\x00 4DNAC101\xf1\xa01.01',
+ b'\xf1\x8756310-L0010\xf1\x00DN8 MDPS C 1.00 1.01 56310-L0010 4DNAC101\xf1\xa01.01',
+ ],
+ (Ecu.fwdCamera, 0x7c4, None): [
+ b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.00 99211-L0000 190716',
+ b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.01 99211-L0000 191016',
+ ],
+ (Ecu.transmission, 0x7e1, None): [
+ b'\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
+ ],
+ },
+ CAR.SANTA_FE: {
+ (Ecu.fwdRadar, 0x7d0, None): [b'\xf1\x00TM__ SCC F-CUP 1.00 1.02 99110-S2000 \xf1\xa01.02'],
+ (Ecu.esp, 0x7d1, None): [b'\xf1\x00TM ESC \x02 100\x18\x030 58910-S2600\xf1\xa01.00',],
+ (Ecu.engine, 0x7e0, None): [b'\xf1\x81606EA051\x00\x00\x00\x00\x00\x00\x00\x00'],
+ (Ecu.eps, 0x7d4, None): [b'\xf1\x00TM MDPS C 1.00 1.00 56340-S2000 8409'],
+ (Ecu.fwdCamera, 0x7c4, None): [b'\xf1\x00TM MFC AT USA LHD 1.00 1.00 99211-S2000 180409'],
+ (Ecu.transmission, 0x7e1, None): [b'\xf1\x87SBJWAA6562474GG0ffvgeTeFx\x88\x97\x88ww\x87www\x87w\x84o\xfa\xff\x87fO\xff\xc2 \xf1\x816W3C2051\x00\x00\xf1\x006W351_C2\x00\x006W3C2051\x00\x00TTM2G24NS1\x00\x00\x00\x00'],
+ },
+ CAR.KIA_STINGER: {
+ (Ecu.fwdRadar, 0x7d0, None): [ b'\xf1\x00CK__ SCC F_CUP 1.00 1.01 96400-J5100 \xf1\xa01.01'],
+ (Ecu.engine, 0x7e0, None): [ b'\xf1\x81640E0051\x00\x00\x00\x00\x00\x00\x00\x00',],
+ (Ecu.eps, 0x7d4, None): [b'\xf1\x00CK MDPS R 1.00 1.04 57700-J5420 4C4VL104'],
+ (Ecu.fwdCamera, 0x7c4, None): [b'\xf1\x00CK MFC AT USA LHD 1.00 1.03 95740-J5000 170822'],
+ (Ecu.transmission, 0x7e1, None): [
+ b'\xf1\x87VDHLG17118862DK2\x8awWwgu\x96wVfUVwv\x97xWvfvUTGTx\x87o\xff\xc9\xed\xf1\x81E21\x00\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 E21\x00\x00\x00\x00\x00\x00\x00SCK0T33NB0\x88\xa2\xe6\xf0',
+ b'\xf1\x87VDHLG17000192DK2xdFffT\xa5VUD$DwT\x86wveVeeD&T\x99\xba\x8f\xff\xcc\x99\xf1\x81E21\x00\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 E21\x00\x00\x00\x00\x00\x00\x00SCK0T33NB0\x88\xa2\xe6\xf0',
+ ],
+ },
+ CAR.KIA_OPTIMA_H: {
+ (Ecu.fwdRadar, 0x7d0, None): [b'\xf1\x00DEhe SCC H-CUP 1.01 1.02 96400-G5100 ',],
+ (Ecu.engine, 0x7e0, None): [b'\xf1\x816H6F4051\x00\x00\x00\x00\x00\x00\x00\x00',],
+ (Ecu.eps, 0x7d4, None): [b'\xf1\x00DE MDPS C 1.00 1.09 56310G5301\x00 4DEHC109',],
+ (Ecu.fwdCamera, 0x7c4, None): [b'\xf1\x00DEP MFC AT USA LHD 1.00 1.01 95740-G5010 170424',],
+ (Ecu.transmission, 0x7e1, None): [b"\xf1\x816U3J2051\x00\x00\xf1\x006U3H0_C2\x00\x006U3J2051\x00\x00PDE0G16NS2\xf4'\\\x91",],
+ },
+ CAR.PALISADE: {
+ (Ecu.fwdRadar, 0x7d0, None): [
+ b'\xf1\x00LX2_ SCC FHCUP 1.00 1.04 99110-S8100 \xf1\xa01.04',
+ b'\xf1\x00LX2 SCC FHCUP 1.00 1.04 99110-S8100 \xf1\xa01.04',
+ ],
+ (Ecu.esp, 0x7d1, None): [
+ b'\xf1\x00LX ESC \x0b 102\x19\x05\x07 58910-S8330',
+ b'\xf1\x00LX ESC \v 102\x19\x05\a 58910-S8330\xf1\xa01.02',
+ b'\xf1\x00LX ESC \v 103\x19\t\x10 58910-S8360\xf1\xa01.03',
+ ],
+ (Ecu.engine, 0x7e0, None): [b'\xf1\x81640J0051\x00\x00\x00\x00\x00\x00\x00\x00',],
+ (Ecu.eps, 0x7d4, None): [b'\xf1\x00LX2 MDPS C 1.00 1.03 56310-S8020 4LXDC103',],
+ (Ecu.fwdCamera, 0x7c4, None): [
+ b'\xf1\x00LX2 MFC AT USA LHD 1.00 1.03 99211-S8100 190125',
+ b'\xf1\x00LX2 MFC AT USA LHD 1.00 1.05 99211-S8100 190909',
+ ],
+ (Ecu.transmission, 0x7e1, None): [
+ b'\xf1\x87LDKVBN424201KF26\xba\xaa\x9a\xa9\x99\x99\x89\x98\x89\x99\xa8\x99\x88\x99\x98\x89\x88\x99\xa8\x89v\x7f\xf7\xffwf_\xffq\xa6\xf1\x81U891\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U891\x00\x00\x00\x00\x00\x00SLX4G38NB2\xafL]\xe7',
+ b'\xf1\x87LDLVBN560098KF26\x86fff\x87vgfg\x88\x96xfw\x86gfw\x86g\x95\xf6\xffeU_\xff\x92c\xf1\x81U891\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U891\x00\x00\x00\x00\x00\x00SLX4G38NB2\xafL]\xe7',
+ ],
+ },
+ CAR.VELOSTER: {
+ (Ecu.fwdRadar, 0x7d0, None): [b'\xf1\x00JS__ SCC H-CUP 1.00 1.02 95650-J3200 ', ],
+ (Ecu.esp, 0x7d1, None): [b'\xf1\x00\x00\x00\x00\x00\x00\x00', ],
+ (Ecu.engine, 0x7e0, None): [b'\x01TJS-JNU06F200H0A', ],
+ (Ecu.eps, 0x7d4, None): [b'\xf1\x00JSL MDPS C 1.00 1.03 56340-J3000 8308', ],
+ (Ecu.fwdCamera, 0x7c4, None): [b'\xf1\x00JS LKAS AT USA LHD 1.00 1.02 95740-J3000 K32', ],
+ (Ecu.transmission, 0x7e1, None): [b'\xf1\x816U2V8051\x00\x00\xf1\x006U2V0_C2\x00\x006U2V8051\x00\x00DJS0T16NS1\xba\x02\xb8\x80', ],
+ },
+ CAR.GENESIS_G70: {
+ (Ecu.fwdRadar, 0x7d0, None): [b'\xf1\x00IK__ SCC F-CUP 1.00 1.02 96400-G9100 \xf1\xa01.02', ],
+ (Ecu.esp, 0x7d1, None): [b'\xf1\x00\x00\x00\x00\x00\x00\x00', ],
+ (Ecu.engine, 0x7e0, None): [b'\xf1\x81640F0051\x00\x00\x00\x00\x00\x00\x00\x00', ],
+ (Ecu.eps, 0x7d4, None): [b'\xf1\x00IK MDPS R 1.00 1.06 57700-G9420 4I4VL106', ],
+ (Ecu.fwdCamera, 0x7c4, None): [b'\xf1\x00IK MFC AT USA LHD 1.00 1.01 95740-G9000 170920', ],
+ (Ecu.transmission, 0x7e1, None): [b'\xf1\x87VDJLT17895112DN4\x88fVf\x99\x88\x88\x88\x87fVe\x88vhwwUFU\x97eFex\x99\xff\xb7\x82\xf1\x81E25\x00\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 E25\x00\x00\x00\x00\x00\x00\x00SIK0T33NB2\x11\x1am\xda', ],
+ },
+ CAR.KONA: {
+ (Ecu.fwdRadar, 0x7d0, None): [b'\xf1\x00OS__ SCC F-CUP 1.00 1.00 95655-J9200 \xf1\xa01.00', ],
+ (Ecu.esp, 0x7d1, None): [b'\xf1\x816V5RAK00018.ELF\xf1\x00\x00\x00\x00\x00\x00\x00\xf1\xa01.05', ],
+ (Ecu.engine, 0x7e0, None): [b'"\x01TOS-0NU06F301J02', ],
+ (Ecu.eps, 0x7d4, None): [b'\xf1\x00OS MDPS C 1.00 1.05 56310J9030\x00 4OSDC105', ],
+ (Ecu.fwdCamera, 0x7c4, None): [b'\xf1\x00OS9 LKAS AT USA LHD 1.00 1.00 95740-J9300 g21', ],
+ (Ecu.transmission, 0x7e1, None): [b'\xf1\x816U2VE051\x00\x00\xf1\x006U2V0_C2\x00\x006U2VE051\x00\x00DOS4T16NS3\x00\x00\x00\x00', ],
+ },
+ CAR.KIA_OPTIMA: {
+ (Ecu.fwdRadar, 0x7d0, None): [b'\xf1\x00JF__ SCC F-CUP 1.00 1.00 96400-D4110 '],
+ (Ecu.esp, 0x7d1, None): [b'\xf1\x00JF ESC \v 11 \x18\x030 58920-D5180',],
+ (Ecu.engine, 0x7e0, None): [b'\x01TJFAJNU06F201H03'],
+ (Ecu.eps, 0x7d4, None): [b'\xf1\x00TM MDPS C 1.00 1.00 56340-S2000 8409'],
+ (Ecu.fwdCamera, 0x7c4, None): [b'\xf1\x00JFA LKAS AT USA LHD 1.00 1.02 95895-D5000 h31'],
+ (Ecu.transmission, 0x7e1, None): [b'\xf1\x816U2V8051\x00\x00\xf1\x006U2V0_C2\x00\x006U2V8051\x00\x00DJF0T16NL0\t\xd2GW'],
+ }
+}
+
CHECKSUM = {
"crc8": [CAR.SANTA_FE, CAR.SONATA, CAR.PALISADE],
"6B": [CAR.KIA_SORENTO, CAR.HYUNDAI_GENESIS],
}
FEATURES = {
- "use_cluster_gears": [CAR.ELANTRA, CAR.KONA, CAR.ELANTRA_GT_I30], # Use Cluster for Gear Selection, rather than Transmission
- "use_tcu_gears": [CAR.KIA_OPTIMA], # Use TCU Message for Gear Selection
- "use_elect_gears": [CAR.KIA_OPTIMA_H, CAR.IONIQ_EV_LTD, CAR.KONA_EV], # Use TCU Message for Gear Selection
+ # which message has the gear
+ "use_cluster_gears": set([CAR.ELANTRA, CAR.ELANTRA_GT_I30, CAR.KONA]),
+ "use_tcu_gears": set([CAR.KIA_OPTIMA, CAR.SONATA_2019, CAR.VELOSTER]),
+ "use_elect_gears": set([CAR.KIA_OPTIMA_H, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.IONIQ]),
+
+ # these cars use the FCA11 message for the AEB and FCW signals, all others use SCC12
+ "use_fca": set([CAR.SONATA, CAR.ELANTRA, CAR.ELANTRA_GT_I30, CAR.KIA_STINGER, CAR.IONIQ, CAR.KONA_EV, CAR.KIA_FORTE, CAR.PALISADE, CAR.GENESIS_G70, CAR.KONA]),
+
+ "use_bsm": set([CAR.SONATA, CAR.PALISADE, CAR.HYUNDAI_GENESIS, CAR.GENESIS_G70, CAR.GENESIS_G80, CAR.GENESIS_G90, CAR.KONA]),
}
+EV_HYBRID = set([CAR.IONIQ_EV_LTD, CAR.IONIQ, CAR.KONA_EV])
+
DBC = {
CAR.ELANTRA: dbc_dict('hyundai_kia_generic', None),
CAR.ELANTRA_GT_I30: dbc_dict('hyundai_kia_generic', None),
+ CAR.GENESIS_G70: dbc_dict('hyundai_kia_generic', None),
CAR.GENESIS_G80: dbc_dict('hyundai_kia_generic', None),
CAR.GENESIS_G90: dbc_dict('hyundai_kia_generic', None),
CAR.HYUNDAI_GENESIS: dbc_dict('hyundai_kia_generic', None),
- CAR.IONIQ: dbc_dict('hyundai_kia_generic', None),
CAR.IONIQ_EV_LTD: dbc_dict('hyundai_kia_generic', None),
+ CAR.IONIQ: dbc_dict('hyundai_kia_generic', None),
CAR.KIA_FORTE: dbc_dict('hyundai_kia_generic', None),
CAR.KIA_OPTIMA: dbc_dict('hyundai_kia_generic', None),
CAR.KIA_OPTIMA_H: dbc_dict('hyundai_kia_generic', None),
@@ -163,7 +290,9 @@ DBC = {
CAR.KONA_EV: dbc_dict('hyundai_kia_generic', None),
CAR.SANTA_FE: dbc_dict('hyundai_kia_generic', None),
CAR.SONATA: dbc_dict('hyundai_kia_generic', None),
+ CAR.SONATA_2019: dbc_dict('hyundai_kia_generic', None),
CAR.PALISADE: dbc_dict('hyundai_kia_generic', None),
+ CAR.VELOSTER: dbc_dict('hyundai_kia_generic', None),
}
STEER_THRESHOLD = 150
diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py
index 65a302000d..bd5c8eb4b7 100644
--- a/selfdrive/car/interfaces.py
+++ b/selfdrive/car/interfaces.py
@@ -7,9 +7,11 @@ from selfdrive.car import gen_empty_fingerprint
from selfdrive.config import Conversions as CV
from selfdrive.controls.lib.events import Events
from selfdrive.controls.lib.vehicle_model import VehicleModel
+from selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX
GearShifter = car.CarState.GearShifter
EventName = car.CarEvent.EventName
+MAX_CTRL_SPEED = (V_CRUISE_MAX + 4) * CV.KPH_TO_MS # 144 + 4 = 92 mph
# generic car and radar interfaces
@@ -21,9 +23,11 @@ class CarInterfaceBase():
self.frame = 0
self.low_speed_alert = False
- self.CS = CarState(CP)
- self.cp = self.CS.get_can_parser(CP)
- self.cp_cam = self.CS.get_cam_can_parser(CP)
+ if CarState is not None:
+ self.CS = CarState(CP)
+ self.cp = self.CS.get_can_parser(CP)
+ self.cp_cam = self.CS.get_cam_can_parser(CP)
+ self.cp_body = self.CS.get_body_can_parser(CP)
self.CC = None
if CarController is not None:
@@ -38,7 +42,7 @@ class CarInterfaceBase():
raise NotImplementedError
@staticmethod
- def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]):
+ def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None):
raise NotImplementedError
# returns a set of default params to avoid repetition in car specific params
@@ -81,7 +85,7 @@ class CarInterfaceBase():
def apply(self, c):
raise NotImplementedError
- def create_common_events(self, cs_out, extra_gears=[], gas_resume_speed=-1, pcm_enable=True):
+ def create_common_events(self, cs_out, extra_gears=[], gas_resume_speed=-1, pcm_enable=True): # pylint: disable=dangerous-default-value
events = Events()
if cs_out.doorOpen:
@@ -102,8 +106,10 @@ class CarInterfaceBase():
events.add(EventName.stockFcw)
if cs_out.stockAeb:
events.add(EventName.stockAeb)
- if cs_out.vEgo > 92 * CV.MPH_TO_MS:
+ if cs_out.vEgo > MAX_CTRL_SPEED:
events.add(EventName.speedTooHigh)
+ if cs_out.cruiseState.nonAdaptive:
+ events.add(EventName.wrongCruiseMode)
if cs_out.steerError:
events.add(EventName.steerUnavailable)
@@ -131,13 +137,12 @@ class RadarInterfaceBase():
self.pts = {}
self.delay = 0
self.radar_ts = CP.radarTimeStep
+ self.no_radar_sleep = 'NO_RADAR_SLEEP' in os.environ
def update(self, can_strings):
ret = car.RadarData.new_message()
-
- if 'NO_RADAR_SLEEP' not in os.environ:
+ if not self.no_radar_sleep:
time.sleep(self.radar_ts) # radard runs on RI updates
-
return ret
class CarStateBase:
@@ -170,3 +175,7 @@ class CarStateBase:
@staticmethod
def get_cam_can_parser(CP):
return None
+
+ @staticmethod
+ def get_body_can_parser(CP):
+ return None
diff --git a/selfdrive/car/isotp_parallel_query.py b/selfdrive/car/isotp_parallel_query.py
index cda36d50fb..c5185dec5c 100644
--- a/selfdrive/car/isotp_parallel_query.py
+++ b/selfdrive/car/isotp_parallel_query.py
@@ -82,7 +82,8 @@ class IsoTpParallelQuery():
id_addr = rx_addr or tx_addr[0]
sub_addr = tx_addr[1]
- can_client = CanClient(self._can_tx, partial(self._can_rx, id_addr, sub_addr=sub_addr), tx_addr[0], rx_addr, self.bus, sub_addr=sub_addr, debug=self.debug)
+ can_client = CanClient(self._can_tx, partial(self._can_rx, id_addr, sub_addr=sub_addr), tx_addr[0], rx_addr,
+ self.bus, sub_addr=sub_addr, debug=self.debug)
max_len = 8 if sub_addr is None else 7
diff --git a/tools/lib/mkvparse/__init__.py b/selfdrive/car/mazda/__init__.py
similarity index 100%
rename from tools/lib/mkvparse/__init__.py
rename to selfdrive/car/mazda/__init__.py
diff --git a/selfdrive/car/mazda/carcontroller.py b/selfdrive/car/mazda/carcontroller.py
new file mode 100644
index 0000000000..20d80e519a
--- /dev/null
+++ b/selfdrive/car/mazda/carcontroller.py
@@ -0,0 +1,43 @@
+from selfdrive.car.mazda import mazdacan
+from selfdrive.car.mazda.values import SteerLimitParams, Buttons
+from opendbc.can.packer import CANPacker
+from selfdrive.car import apply_std_steer_torque_limits
+
+class CarController():
+ def __init__(self, dbc_name, CP, VM):
+ self.apply_steer_last = 0
+ self.packer = CANPacker(dbc_name)
+ self.steer_rate_limited = False
+
+ def update(self, enabled, CS, frame, actuators):
+ """ Controls thread """
+
+ can_sends = []
+
+ ### STEER ###
+
+ if enabled:
+ # calculate steer and also set limits due to driver torque
+ new_steer = int(round(actuators.steer * SteerLimitParams.STEER_MAX))
+ apply_steer = apply_std_steer_torque_limits(new_steer, self.apply_steer_last,
+ CS.out.steeringTorque, SteerLimitParams)
+ self.steer_rate_limited = new_steer != apply_steer
+
+ if CS.out.standstill and frame % 20 == 0:
+ # Mazda Stop and Go requires a RES button (or gas) press if the car stops more than 3 seconds
+ # Send Resume button at 5hz if we're engaged at standstill to support full stop and go!
+ # TODO: improve the resume trigger logic by looking at actual radar data
+ can_sends.append(mazdacan.create_button_cmd(self.packer, CS.CP.carFingerprint, Buttons.RESUME))
+ else:
+ apply_steer = 0
+ self.steer_rate_limited = False
+ if CS.out.cruiseState.enabled and frame % 20 == 0:
+ # Cancel Stock ACC if it's enabled while OP is disengaged
+ # Send at a rate of 5hz until we sync with stock ACC state
+ can_sends.append(mazdacan.create_button_cmd(self.packer, CS.CP.carFingerprint, Buttons.CANCEL))
+
+ self.apply_steer_last = apply_steer
+
+ can_sends.append(mazdacan.create_steering_control(self.packer, CS.CP.carFingerprint,
+ frame, apply_steer, CS.cam_lkas))
+ return can_sends
diff --git a/selfdrive/car/mazda/carstate.py b/selfdrive/car/mazda/carstate.py
new file mode 100644
index 0000000000..03f3a026b5
--- /dev/null
+++ b/selfdrive/car/mazda/carstate.py
@@ -0,0 +1,188 @@
+from cereal import car
+from selfdrive.config import Conversions as CV
+from opendbc.can.can_define import CANDefine
+from opendbc.can.parser import CANParser
+from selfdrive.car.interfaces import CarStateBase
+from selfdrive.car.mazda.values import DBC, LKAS_LIMITS, CAR
+
+class CarState(CarStateBase):
+ def __init__(self, CP):
+ super().__init__(CP)
+
+ can_define = CANDefine(DBC[CP.carFingerprint]['pt'])
+ self.shifter_values = can_define.dv["GEAR"]['GEAR']
+
+ self.cruise_speed = 0
+ self.acc_active_last = False
+ self.low_speed_lockout = True
+ self.low_speed_alert = False
+ self.lkas_allowed = False
+
+ def update(self, cp, cp_cam):
+
+ ret = car.CarState.new_message()
+ ret.wheelSpeeds.fl = cp.vl["WHEEL_SPEEDS"]['FL'] * CV.KPH_TO_MS
+ ret.wheelSpeeds.fr = cp.vl["WHEEL_SPEEDS"]['FR'] * CV.KPH_TO_MS
+ ret.wheelSpeeds.rl = cp.vl["WHEEL_SPEEDS"]['RL'] * CV.KPH_TO_MS
+ ret.wheelSpeeds.rr = cp.vl["WHEEL_SPEEDS"]['RR'] * CV.KPH_TO_MS
+ ret.vEgoRaw = (ret.wheelSpeeds.fl + ret.wheelSpeeds.fr + ret.wheelSpeeds.rl + ret.wheelSpeeds.rr) / 4.
+ ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
+
+ # Match panda speed reading
+ speed_kph = cp.vl["ENGINE_DATA"]['SPEED']
+ ret.standstill = speed_kph < .1
+
+ can_gear = int(cp.vl["GEAR"]['GEAR'])
+ ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(can_gear, None))
+
+ ret.leftBlinker = cp.vl["BLINK_INFO"]['LEFT_BLINK'] == 1
+ ret.rightBlinker = cp.vl["BLINK_INFO"]['RIGHT_BLINK'] == 1
+
+ ret.steeringAngle = cp.vl["STEER"]['STEER_ANGLE']
+ ret.steeringTorque = cp.vl["STEER_TORQUE"]['STEER_TORQUE_SENSOR']
+ ret.steeringPressed = abs(ret.steeringTorque) > LKAS_LIMITS.STEER_THRESHOLD
+
+ ret.steeringTorqueEps = cp.vl["STEER_TORQUE"]['STEER_TORQUE_MOTOR']
+ ret.steeringRate = cp.vl["STEER_RATE"]['STEER_ANGLE_RATE']
+
+ ret.brakePressed = cp.vl["PEDALS"]['BRAKE_ON'] == 1
+ ret.brake = cp.vl["BRAKE"]['BRAKE_PRESSURE']
+ ret.brakeLights = ret.brakePressed
+
+ ret.seatbeltUnlatched = cp.vl["SEATBELT"]['DRIVER_SEATBELT'] == 0
+ ret.doorOpen = any([cp.vl["DOORS"]['FL'], cp.vl["DOORS"]['FR'],
+ cp.vl["DOORS"]['BL'], cp.vl["DOORS"]['BR']])
+
+ ret.gas = cp.vl["ENGINE_DATA"]['PEDAL_GAS']
+ ret.gasPressed = ret.gas > 0
+
+ ret.leftBlindspot = cp.vl["BSM"]['LEFT_BS1'] == 1
+ ret.rightBlindspot = cp.vl["BSM"]['RIGHT_BS1'] == 1
+
+ # LKAS is enabled at 52kph going up and disabled at 45kph going down
+ if speed_kph > LKAS_LIMITS.ENABLE_SPEED:
+ self.lkas_allowed = True
+ elif speed_kph < LKAS_LIMITS.DISABLE_SPEED:
+ self.lkas_allowed = False
+
+ # if any of the cruize buttons is pressed force state update
+ if any([cp.vl["CRZ_BTNS"]['RES'],
+ cp.vl["CRZ_BTNS"]['SET_P'],
+ cp.vl["CRZ_BTNS"]['SET_M']]):
+ self.cruise_speed = ret.vEgoRaw
+
+ ret.cruiseState.available = True
+ ret.cruiseState.enabled = cp.vl["CRZ_CTRL"]['CRZ_ACTIVE'] == 1
+ ret.cruiseState.speed = self.cruise_speed
+
+ if ret.cruiseState.enabled:
+ if not self.lkas_allowed:
+ if not self.acc_active_last:
+ self.low_speed_lockout = True
+ else:
+ self.low_speed_alert = True
+ else:
+ self.low_speed_lockout = False
+ self.low_speed_alert = False
+
+ # On if no driver torque the last 5 seconds
+ ret.steerWarning = cp.vl["STEER_RATE"]['HANDS_OFF_5_SECONDS'] == 1
+
+ self.acc_active_last = ret.cruiseState.enabled
+
+ self.cam_lkas = cp_cam.vl["CAM_LKAS"]
+ ret.steerError = cp_cam.vl["CAM_LKAS"]['ERR_BIT_1'] == 1
+
+ return ret
+
+ @staticmethod
+ def get_can_parser(CP):
+ # this function generates lists for signal, messages and initial values
+ signals = [
+ # sig_name, sig_address, default
+ ("LEFT_BLINK", "BLINK_INFO", 0),
+ ("RIGHT_BLINK", "BLINK_INFO", 0),
+ ("STEER_ANGLE", "STEER", 0),
+ ("STEER_ANGLE_RATE", "STEER_RATE", 0),
+ ("STEER_TORQUE_SENSOR", "STEER_TORQUE", 0),
+ ("STEER_TORQUE_MOTOR", "STEER_TORQUE", 0),
+ ("FL", "WHEEL_SPEEDS", 0),
+ ("FR", "WHEEL_SPEEDS", 0),
+ ("RL", "WHEEL_SPEEDS", 0),
+ ("RR", "WHEEL_SPEEDS", 0),
+ ]
+
+ checks = [
+ # sig_address, frequency
+ ("BLINK_INFO", 10),
+ ("STEER", 67),
+ ("STEER_RATE", 83),
+ ("STEER_TORQUE", 83),
+ ("WHEEL_SPEEDS", 100),
+ ]
+
+ if CP.carFingerprint == CAR.CX5:
+ signals += [
+ ("LKAS_BLOCK", "STEER_RATE", 0),
+ ("LKAS_TRACK_STATE", "STEER_RATE", 0),
+ ("HANDS_OFF_5_SECONDS", "STEER_RATE", 0),
+ ("CRZ_ACTIVE", "CRZ_CTRL", 0),
+ ("STANDSTILL", "PEDALS", 0),
+ ("BRAKE_ON", "PEDALS", 0),
+ ("BRAKE_PRESSURE", "BRAKE", 0),
+ ("GEAR", "GEAR", 0),
+ ("DRIVER_SEATBELT", "SEATBELT", 0),
+ ("FL", "DOORS", 0),
+ ("FR", "DOORS", 0),
+ ("BL", "DOORS", 0),
+ ("BR", "DOORS", 0),
+ ("PEDAL_GAS", "ENGINE_DATA", 0),
+ ("SPEED", "ENGINE_DATA", 0),
+ ("RES", "CRZ_BTNS", 0),
+ ("SET_P", "CRZ_BTNS", 0),
+ ("SET_M", "CRZ_BTNS", 0),
+ ("CTR", "CRZ_BTNS", 0),
+ ("LEFT_BS1", "BSM", 0),
+ ("RIGHT_BS1", "BSM", 0),
+ ]
+
+ checks += [
+ ("ENGINE_DATA", 100),
+ ("CRZ_CTRL", 50),
+ ("CRZ_BTNS", 10),
+ ("PEDALS", 50),
+ ("BRAKE", 50),
+ ("SEATBELT", 10),
+ ("DOORS", 10),
+ ("GEAR", 20),
+ ("BSM", 10),
+ ]
+
+ return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 0)
+
+ @staticmethod
+ def get_cam_can_parser(CP):
+ signals = []
+ checks = []
+
+ if CP.carFingerprint == CAR.CX5:
+ signals += [
+ # sig_name, sig_address, default
+ ("LKAS_REQUEST", "CAM_LKAS", 0),
+ ("CTR", "CAM_LKAS", 0),
+ ("ERR_BIT_1", "CAM_LKAS", 0),
+ ("LINE_NOT_VISIBLE", "CAM_LKAS", 0),
+ ("LDW", "CAM_LKAS", 0),
+ ("BIT_1", "CAM_LKAS", 1),
+ ("ERR_BIT_2", "CAM_LKAS", 0),
+ ("STEERING_ANGLE", "CAM_LKAS", 0),
+ ("ANGLE_ENABLED", "CAM_LKAS", 0),
+ ("CHKSUM", "CAM_LKAS", 0),
+ ]
+
+ checks += [
+ # sig_address, frequency
+ ("CAM_LKAS", 16),
+ ]
+
+ return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2)
diff --git a/selfdrive/car/mazda/interface.py b/selfdrive/car/mazda/interface.py
new file mode 100755
index 0000000000..dfa959da38
--- /dev/null
+++ b/selfdrive/car/mazda/interface.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+from cereal import car
+from selfdrive.config import Conversions as CV
+from selfdrive.car.mazda.values import CAR, LKAS_LIMITS, FINGERPRINTS, ECU_FINGERPRINT, Ecu
+from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, is_ecu_disconnected
+from selfdrive.car.interfaces import CarInterfaceBase
+
+ButtonType = car.CarState.ButtonEvent.Type
+EventName = car.CarEvent.EventName
+
+class CarInterface(CarInterfaceBase):
+
+ @staticmethod
+ def compute_gb(accel, speed):
+ return float(accel) / 4.0
+
+ @staticmethod
+ def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None):
+ ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay)
+
+ ret.carName = "mazda"
+ ret.safetyModel = car.CarParams.SafetyModel.mazda
+
+ ret.dashcamOnly = True
+
+ ret.radarOffCan = True
+
+ # Mazda port is a community feature for now
+ ret.communityFeature = True
+
+ ret.steerActuatorDelay = 0.1
+ ret.steerRateCost = 1.0
+ ret.steerLimitTimer = 0.8
+ tire_stiffness_factor = 0.70 # not optimized yet
+
+ if candidate in [CAR.CX5]:
+ ret.mass = 3655 * CV.LB_TO_KG + STD_CARGO_KG
+ ret.wheelbase = 2.7
+ ret.steerRatio = 15.5
+
+ ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.2]]
+
+ ret.lateralTuning.pid.kf = 0.00006
+
+ # No steer below disable speed
+ ret.minSteerSpeed = LKAS_LIMITS.DISABLE_SPEED * CV.KPH_TO_MS
+
+ ret.centerToFront = ret.wheelbase * 0.41
+
+ # TODO: get actual value, for now starting with reasonable value for
+ # civic and scaling by mass and wheelbase
+ ret.rotationalInertia = scale_rot_inertia(ret.mass, ret.wheelbase)
+
+ # TODO: start from empirically derived lateral slip stiffness for the civic and scale by
+ # mass and CG position, so all cars will have approximately similar dyn behaviors
+ ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront,
+ tire_stiffness_factor=tire_stiffness_factor)
+
+ ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, Ecu.fwdCamera) or has_relay
+
+ return ret
+
+ # returns a car.CarState
+ def update(self, c, can_strings):
+
+ self.cp.update_strings(can_strings)
+ self.cp_cam.update_strings(can_strings)
+
+ ret = self.CS.update(self.cp, self.cp_cam)
+ ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
+
+ # events
+ events = self.create_common_events(ret)
+
+ if self.CS.low_speed_lockout:
+ events.add(EventName.belowEngageSpeed)
+
+ if self.CS.low_speed_alert:
+ events.add(EventName.belowSteerSpeed)
+
+ ret.events = events.to_msg()
+
+ self.CS.out = ret.as_reader()
+ return self.CS.out
+
+ def apply(self, c):
+ can_sends = self.CC.update(c.enabled, self.CS, self.frame, c.actuators)
+ self.frame += 1
+ return can_sends
diff --git a/selfdrive/car/mazda/mazdacan.py b/selfdrive/car/mazda/mazdacan.py
new file mode 100644
index 0000000000..55b9218dbd
--- /dev/null
+++ b/selfdrive/car/mazda/mazdacan.py
@@ -0,0 +1,104 @@
+from selfdrive.car.mazda.values import CAR, Buttons
+
+def create_steering_control(packer, car_fingerprint, frame, apply_steer, lkas):
+
+ tmp = apply_steer + 2048
+
+ lo = tmp & 0xFF
+ hi = tmp >> 8
+
+ b1 = int(lkas["BIT_1"])
+ ldw = int(lkas["LDW"])
+ er1 = int(lkas["ERR_BIT_1"])
+ lnv = 0
+ er2 = int(lkas["ERR_BIT_2"])
+
+ steering_angle = int(lkas["STEERING_ANGLE"])
+ b2 = int(lkas["ANGLE_ENABLED"])
+
+ tmp = steering_angle + 2048
+ ahi = tmp >> 10
+ amd = (tmp & 0x3FF) >> 2
+ amd = (amd >> 4) | (( amd & 0xF) << 4)
+ alo = (tmp & 0x3) << 2
+
+ ctr = frame % 16
+ # bytes: [ 1 ] [ 2 ] [ 3 ] [ 4 ]
+ csum = 249 - ctr - hi - lo - (lnv << 3) - er1 - (ldw << 7) - ( er2 << 4) - (b1 << 5)
+
+ #bytes [ 5 ] [ 6 ] [ 7 ]
+ csum = csum - ahi - amd - alo - b2
+
+ if ahi == 1:
+ csum = csum + 15
+
+ if csum < 0:
+ if csum < -256:
+ csum = csum + 512
+ else:
+ csum = csum + 256
+
+ csum = csum % 256
+
+ if car_fingerprint == CAR.CX5:
+ values = {
+ "LKAS_REQUEST" : apply_steer,
+ "CTR" : ctr,
+ "ERR_BIT_1" : er1,
+ "LINE_NOT_VISIBLE" : lnv,
+ "LDW" : ldw,
+ "BIT_1" : b1,
+ "ERR_BIT_2" : er2,
+ "STEERING_ANGLE" : steering_angle,
+ "ANGLE_ENABLED" : b2,
+ "CHKSUM" : csum
+ }
+
+ return packer.make_can_msg("CAM_LKAS", 0, values)
+
+
+def create_button_cmd(packer, car_fingerprint, button):
+
+ if button == Buttons.CANCEL:
+ can = 1
+ res = 0
+ elif button == Buttons.RESUME:
+ can = 0
+ res = 1
+ else:
+ can = 0
+ res = 0
+
+ if car_fingerprint == CAR.CX5:
+ values = {
+ "CAN_OFF" : can,
+ "CAN_OFF_INV" : (can + 1) % 2,
+
+ "SET_P" : 0,
+ "SET_P_INV" : 1,
+
+ "RES" : res,
+ "RES_INV" : (res + 1) % 2,
+
+ "SET_M" : 0,
+ "SET_M_INV" : 1,
+
+ "DISTANCE_LESS" : 0,
+ "DISTANCE_LESS_INV" : 1,
+
+ "DISTANCE_MORE" : 0,
+ "DISTANCE_MORE_INV" : 1,
+
+ "MODE_X" : 0,
+ "MODE_X_INV" : 1,
+
+ "MODE_Y" : 0,
+ "MODE_Y_INV" : 1,
+
+ "BIT1" : 1,
+ "BIT2" : 1,
+ "BIT3" : 1,
+ "CTR" : 0
+ }
+
+ return packer.make_can_msg("CRZ_BTNS", 0, values)
diff --git a/selfdrive/car/mazda/radar_interface.py b/selfdrive/car/mazda/radar_interface.py
new file mode 100755
index 0000000000..b2f7651136
--- /dev/null
+++ b/selfdrive/car/mazda/radar_interface.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python3
+from selfdrive.car.interfaces import RadarInterfaceBase
+
+class RadarInterface(RadarInterfaceBase):
+ pass
diff --git a/selfdrive/car/mazda/values.py b/selfdrive/car/mazda/values.py
new file mode 100644
index 0000000000..5759d431a8
--- /dev/null
+++ b/selfdrive/car/mazda/values.py
@@ -0,0 +1,76 @@
+# flake8: noqa
+
+from selfdrive.car import dbc_dict
+from cereal import car
+Ecu = car.CarParams.Ecu
+
+
+# Steer torque limits
+
+class SteerLimitParams:
+ STEER_MAX = 600 # max_steer 2048
+ STEER_STEP = 1 # how often we update the steer cmd
+ STEER_DELTA_UP = 10 # torque increase per refresh
+ STEER_DELTA_DOWN = 20 # torque decrease per refresh
+ STEER_DRIVER_ALLOWANCE = 15 # allowed driver torque before start limiting
+ STEER_DRIVER_MULTIPLIER = 1 # weight driver torque
+ STEER_DRIVER_FACTOR = 1 # from dbc
+
+class CAR:
+ CX5 = "Mazda CX-5 2017"
+
+class LKAS_LIMITS:
+ STEER_THRESHOLD = 15
+ DISABLE_SPEED = 45 # kph
+ ENABLE_SPEED = 52 # kph
+
+class Buttons:
+ NONE = 0
+ SET_PLUS = 1
+ SET_MINUS = 2
+ RESUME = 3
+ CANCEL = 4
+
+FINGERPRINTS = {
+ CAR.CX5: [
+ # CX-5 2017 GT
+ {
+ 64: 8, 70: 8, 80: 8, 117: 8, 118: 8, 120: 8, 121: 8, 130: 8, 134: 8, 145: 8, 154: 8, 155: 8, 157: 8, 158: 8, 159: 8, 253: 8, 304: 8, 305: 8, 357: 8, 358: 8, 359: 8, 512: 8, 514: 8, 515: 8, 529: 8, 533: 8, 535: 8, 539: 8, 540: 8, 541: 8, 542: 8, 543: 8, 552: 8, 576: 8, 577: 8, 578: 8, 579: 8, 580: 8, 581: 8, 582: 8, 605: 8, 606: 8, 607: 8, 608: 8, 628: 8, 832: 8, 836: 8, 863: 8, 865: 8, 866: 8, 867: 8, 868: 8, 869: 8, 870: 8, 976: 8, 977: 8, 978: 8, 1034: 8, 1045: 8, 1056: 8, 1061: 8, 1067: 8, 1070: 8, 1078: 8, 1080: 8, 1085: 8, 1086: 8, 1088: 8, 1093: 8, 1108: 8, 1114: 8, 1115: 8, 1116: 8, 1139: 8, 1143: 8, 1147: 8, 1154: 8, 1157: 8, 1160: 8, 1163: 8, 1166: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1183: 8, 1233: 8, 1236: 8, 1237: 8, 1238: 8, 1239: 8, 1241: 8, 1242: 8, 1243: 8, 1244: 8, 1264: 8, 1266: 8, 1267: 8, 1269: 8, 1270: 8, 1271: 8, 1272: 8, 1274: 8, 1275: 8, 1277: 8, 1278: 8, 1409: 8, 1416: 8, 1425: 8, 1430: 8, 1435: 8, 1440: 8, 1446: 8, 1456: 8, 1479: 8
+ },
+
+ # CX-5 2019 GTR
+ {
+ 64: 8, 70: 8, 80: 8, 117: 8, 118: 8, 120: 8, 121: 8, 130: 8, 134: 8, 145: 8, 154: 8, 155: 8, 157: 8, 158: 8, 159: 8, 253: 8, 254: 8, 304: 8, 305: 8, 357: 8, 358: 8, 359: 8, 512: 8, 514: 8, 515: 8, 529: 8, 533: 8, 535: 8, 539: 8, 540: 8, 541: 8, 542: 8, 543: 8, 552: 8, 576: 8, 577: 8, 578: 8, 579: 8, 580: 8, 581: 8, 582: 8, 605: 8, 606: 8, 607: 8, 608: 8, 628: 8, 736: 8, 832: 8, 836: 8, 863: 8, 865: 8, 866: 8, 867: 8, 868: 8, 869: 8, 870: 8, 976: 8, 977: 8, 978: 8, 1034: 8, 1045: 8, 1056: 8, 1061: 8, 1067: 8, 1078: 8, 1080: 8, 1085: 8, 1086: 8, 1088: 8, 1093: 8, 1108: 8, 1114: 8, 1115: 8, 1116: 8, 1139: 8, 1143: 8, 1147: 8, 1154: 8, 1157: 8, 1160: 8, 1163: 8, 1166: 8, 1170: 8, 1171: 8, 1173: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1183: 8, 1233: 8, 1236: 8, 1237: 8, 1238: 8, 1239: 8, 1241: 8, 1242: 8, 1244: 8, 1260: 8, 1264: 8, 1266: 8, 1267: 8, 1269: 8, 1270: 8, 1271: 8, 1272: 8, 1274: 8, 1277: 8, 1278: 8, 1409: 8, 1416: 8, 1425: 8, 1430: 8, 1435: 8, 1440: 8, 1446: 8, 1456: 8, 1479: 8, 1776: 8, 1792: 8, 1872: 8, 1937: 8, 1953: 8, 1968: 8, 2015: 8, 2016: 8, 2024: 8
+ },
+
+ # Mazda 6 2017 GT
+ {
+ 64: 8, 70: 8, 80: 8, 117: 8, 118: 8, 120: 8, 121: 8, 130: 8, 134: 8, 145: 8, 154: 8, 155: 8, 157: 8, 158: 8, 159: 8, 253: 8, 304: 8, 305: 8, 357: 8, 358: 8, 359: 8, 512: 8, 514: 8, 515: 8, 529: 8, 533: 8, 535: 8, 539: 8, 540: 8, 541: 8, 542: 8, 543: 8, 552: 8, 576: 8, 577: 8, 578: 8, 579: 8, 580: 8, 581: 8, 582: 8, 605: 8, 606: 8, 607: 8, 628: 8, 832: 8, 836: 8, 863: 8, 865: 8, 866: 8, 867: 8, 868: 8, 869: 8, 870: 8, 976: 8, 977: 8, 978: 8, 1034: 8, 1045: 8, 1056: 8, 1061: 8, 1067: 8, 1070: 8, 1078: 8, 1080: 8, 1085: 8, 1086: 8, 1088: 8, 1093: 8, 1108: 8, 1114: 8, 1115: 8, 1116: 8, 1143: 8, 1147: 8, 1154: 8, 1157: 8, 1160: 8, 1163: 8, 1166: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1182: 8, 1183: 8, 1233: 8, 1236: 8, 1237: 8, 1238: 8, 1239: 8, 1241: 8, 1242: 8, 1243: 8, 1244: 8, 1264: 8, 1266: 8, 1267: 8, 1269: 8, 1270: 8, 1271: 8, 1272: 8, 1274: 8, 1275: 8, 1277: 8, 1278: 8, 1409: 8, 1416: 8, 1425: 8, 1430: 8, 1435: 8, 1440: 8, 1456: 8, 1479: 8
+ },
+
+ # CX-9 2017 Australia - old CAM connector
+ {
+ 64: 8, 70: 8, 80: 8, 117: 8, 118: 8, 120: 8, 121: 8, 130: 8, 134: 8, 138: 8, 145: 8, 154: 8, 155: 8, 157: 8, 158: 8, 159: 8, 253: 8, 304: 8, 305: 8, 357: 8, 358: 8, 359: 8, 512: 8, 514: 8, 515: 8, 522: 8, 529: 8, 533: 8, 535: 8, 539: 8, 540: 8, 541: 8, 542: 8, 543: 8, 552: 8, 576: 8, 577: 8, 578: 8, 579: 8, 580: 8, 581: 8, 582: 8, 583: 8, 605: 8, 606: 8, 628: 8, 832: 8, 976: 8, 977: 8, 978: 8, 1034: 8, 1045: 8, 1056: 8, 1061: 8, 1067: 8, 1078: 8, 1085: 8, 1086: 8, 1088: 8, 1093: 8, 1108: 8, 1114: 8, 1115: 8, 1116: 8, 1139: 8, 1143: 8, 1147: 8, 1154: 8, 1157: 8, 1160: 8, 1163: 8, 1166: 8, 1170: 8, 1177: 8, 1180: 8, 1183: 8, 1233: 8, 1236: 8, 1237: 8, 1238: 8, 1239: 8, 1241: 8, 1242: 8, 1243: 8, 1244: 8, 1247: 8, 1264: 8, 1266: 8, 1267: 8, 1269: 8, 1271: 8, 1272: 8, 1274: 8, 1277: 8, 1278: 8, 1409: 8, 1416: 8, 1425: 8, 1430: 8, 1435: 8, 1440: 8, 1446: 8, 1456: 8, 1479: 8
+ },
+
+ # CX-9 2016 - old CAM connector
+ {
+ 64: 8, 70: 8, 80: 8, 117: 8, 118: 8, 120: 8, 121: 8, 130: 8, 134: 8, 145: 8, 154: 8, 155: 8, 157: 8, 158: 8, 159: 8, 253: 8, 304: 8, 305: 8, 357: 8, 358: 8, 359: 8, 512: 8, 514: 8, 515: 8, 529: 8, 533: 8, 535: 8, 539: 8, 540: 8, 541: 8, 542: 8, 543: 8, 552: 8, 576: 8, 577: 8, 578: 8, 579: 8, 580: 8, 581: 8, 582: 8, 583: 8, 605: 8, 606: 8, 608: 8, 628: 8, 832: 8, 836: 8, 976: 8, 977: 8, 978: 8, 1034: 8, 1045: 8, 1056: 8, 1061: 8, 1067: 8, 1078: 8, 1080: 8, 1085: 8, 1086: 8, 1088: 8, 1093: 8, 1108: 8, 1114: 8, 1115: 8, 1116: 8, 1139: 8, 1143: 8, 1147: 8, 1154: 8, 1157: 8, 1160: 8, 1163: 8, 1166: 8, 1170: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1183: 8, 1233: 8, 1236: 8, 1237: 8, 1238: 8, 1239: 8, 1241: 8, 1242: 8, 1244: 8, 1264: 8, 1266: 8, 1267: 8, 1269: 8, 1271: 8, 1272: 8, 1274: 8, 1277: 8, 1278: 8, 1409: 8, 1416: 8, 1425: 8, 1430: 8, 1435: 8, 1440: 8, 1446: 8, 1456: 8, 1479: 8, 1792: 8, 1872: 8, 1937: 8, 1953: 8, 1968: 8, 1988: 8, 1996: 8, 2000: 8, 2001: 8, 2004: 8, 2015: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8
+ },
+
+ # Mazda 3 2017
+ {
+ 19: 5, 80: 8, 117: 8, 118: 8, 120: 8, 121: 8, 130: 8, 134: 8, 145: 8, 154: 8, 155: 8, 157: 8, 158: 8, 159: 8, 253: 8, 304: 8, 305: 8, 357: 8, 358: 8, 359: 8, 512: 8, 514: 8, 515: 8, 529: 8, 533: 8, 535: 8, 539: 8, 540: 8, 541: 8, 542: 8, 543: 8, 552: 8, 576: 8, 577: 8, 578: 8, 579: 8, 580: 8, 581: 8, 582: 8, 605: 8, 606: 8, 607: 8, 628: 8, 832: 8, 863: 8, 865: 8, 866: 8, 867: 8, 868: 8, 869: 8, 870: 8, 976: 8, 977: 8, 978: 8, 1034: 8, 1045: 8, 1056: 8, 1061: 8, 1067: 8, 1070: 8, 1078: 8, 1086: 8, 1088: 8, 1093: 8, 1108: 8, 1114: 8, 1115: 8, 1116: 8, 1143: 8, 1147: 8, 1154: 8, 1157: 8, 1160: 8, 1163: 8, 1166: 8, 1169: 8, 1170: 8, 1173: 8, 1177: 8, 1180: 8, 1182: 8, 1183: 8, 1233: 8, 1236: 8, 1237: 8, 1238: 8, 1239: 8, 1241: 8, 1242: 8, 1243: 8, 1244: 8, 1264: 8, 1266: 8, 1267: 8, 1269: 8, 1270: 8, 1271: 8, 1272: 8, 1274: 8, 1275: 8, 1277: 8, 1278: 8, 1409: 8, 1416: 8, 1425: 8, 1430: 8, 1435: 8, 1440: 8, 1456: 8, 1479: 8, 2015: 8, 2024: 8, 2025: 8
+ },
+ ],
+
+}
+
+ECU_FINGERPRINT = {
+ Ecu.fwdCamera: [579], # steer torque cmd
+}
+
+
+DBC = {
+ CAR.CX5: dbc_dict('mazda_2017', None),
+}
diff --git a/selfdrive/car/mock/interface.py b/selfdrive/car/mock/interface.py
index 69b3862df4..d0298ec838 100755
--- a/selfdrive/car/mock/interface.py
+++ b/selfdrive/car/mock/interface.py
@@ -8,7 +8,7 @@ from selfdrive.car.interfaces import CarInterfaceBase
# mocked car interface to work with chffrplus
TS = 0.01 # 100Hz
-YAW_FR = 0.2 # ~0.8s time constant on yaw rate filter
+YAW_FR = 0.2 # ~0.8s time constant on yaw rate filter
# low pass gain
LPG = 2 * 3.1415 * YAW_FR * TS / (1 + 2 * 3.1415 * YAW_FR * TS)
@@ -33,7 +33,7 @@ class CarInterface(CarInterfaceBase):
return accel
@staticmethod
- def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]):
+ def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay)
ret.carName = "mock"
ret.safetyModel = car.CarParams.SafetyModel.noOutput
@@ -41,7 +41,7 @@ class CarInterface(CarInterfaceBase):
ret.rotationalInertia = 2500.
ret.wheelbase = 2.70
ret.centerToFront = ret.wheelbase * 0.5
- ret.steerRatio = 13. # reasonable
+ ret.steerRatio = 13. # reasonable
ret.tireStiffnessFront = 1e6 # very stiff to neglect slip
ret.tireStiffnessRear = 1e6 # very stiff to neglect slip
diff --git a/selfdrive/car/nissan/carcontroller.py b/selfdrive/car/nissan/carcontroller.py
index 56e2ae7522..5838d67ae3 100644
--- a/selfdrive/car/nissan/carcontroller.py
+++ b/selfdrive/car/nissan/carcontroller.py
@@ -2,7 +2,7 @@ from cereal import car
from common.numpy_fast import clip, interp
from selfdrive.car.nissan import nissancan
from opendbc.can.packer import CANPacker
-from selfdrive.car.nissan.values import CAR
+from selfdrive.car.nissan.values import CAR, STEER_THRESHOLD
# Steer angle limits
ANGLE_DELTA_BP = [0., 5., 15.]
@@ -53,7 +53,11 @@ class CarController():
else:
# Scale max torque based on how much torque the driver is applying to the wheel
self.lkas_max_torque = max(
- 0, LKAS_MAX_TORQUE - 0.4 * abs(CS.out.steeringTorque))
+ # Scale max torque down to half LKAX_MAX_TORQUE as a minimum
+ LKAS_MAX_TORQUE * 0.5,
+ # Start scaling torque at STEER_THRESHOLD
+ LKAS_MAX_TORQUE - 0.6 * max(0, abs(CS.out.steeringTorque) - STEER_THRESHOLD)
+ )
else:
apply_angle = CS.out.steeringAngle
@@ -65,7 +69,7 @@ class CarController():
# send acc cancel cmd if drive is disabled but pcm is still on, or if the system can't be activated
cruise_cancel = 1
- if self.CP.carFingerprint == CAR.XTRAIL and cruise_cancel:
+ if self.CP.carFingerprint in [CAR.ROGUE, CAR.XTRAIL] and cruise_cancel:
can_sends.append(nissancan.create_acc_cancel_cmd(self.packer, CS.cruise_throttle_msg, frame))
# TODO: Find better way to cancel!
diff --git a/selfdrive/car/nissan/carstate.py b/selfdrive/car/nissan/carstate.py
index 849e89b731..f2076183d9 100644
--- a/selfdrive/car/nissan/carstate.py
+++ b/selfdrive/car/nissan/carstate.py
@@ -1,4 +1,5 @@
import copy
+from collections import deque
from cereal import car
from opendbc.can.can_define import CANDefine
from selfdrive.car.interfaces import CarStateBase
@@ -6,30 +7,32 @@ from selfdrive.config import Conversions as CV
from opendbc.can.parser import CANParser
from selfdrive.car.nissan.values import CAR, DBC, STEER_THRESHOLD
+TORQUE_SAMPLES = 12
class CarState(CarStateBase):
def __init__(self, CP):
super().__init__(CP)
can_define = CANDefine(DBC[CP.carFingerprint]['pt'])
+ self.steeringTorqueSamples = deque(TORQUE_SAMPLES*[0], TORQUE_SAMPLES)
self.shifter_values = can_define.dv["GEARBOX"]["GEAR_SHIFTER"]
def update(self, cp, cp_adas, cp_cam):
ret = car.CarState.new_message()
- if self.CP.carFingerprint == CAR.XTRAIL:
+ if self.CP.carFingerprint in [CAR.ROGUE, CAR.XTRAIL]:
ret.gas = cp.vl["GAS_PEDAL"]["GAS_PEDAL"]
elif self.CP.carFingerprint == CAR.LEAF:
ret.gas = cp.vl["CRUISE_THROTTLE"]["GAS_PEDAL"]
ret.gasPressed = bool(ret.gas > 3)
- if self.CP.carFingerprint == CAR.XTRAIL:
+ if self.CP.carFingerprint in [CAR.ROGUE, CAR.XTRAIL]:
ret.brakePressed = bool(cp.vl["DOORS_LIGHTS"]["USER_BRAKE_PRESSED"])
elif self.CP.carFingerprint == CAR.LEAF:
ret.brakePressed = bool(cp.vl["BRAKE_PEDAL"]["BRAKE_PEDAL"] > 3)
- if self.CP.carFingerprint == CAR.XTRAIL:
+ if self.CP.carFingerprint in [CAR.ROGUE, CAR.XTRAIL]:
ret.brakeLights = bool(cp.vl["DOORS_LIGHTS"]["BRAKE_LIGHT"])
ret.wheelSpeeds.fl = cp.vl["WHEEL_SPEEDS_FRONT"]["WHEEL_SPEED_FL"] * CV.KPH_TO_MS
@@ -43,24 +46,26 @@ class CarState(CarStateBase):
ret.standstill = ret.vEgoRaw < 0.01
ret.cruiseState.enabled = bool(cp_adas.vl["CRUISE_STATE"]["CRUISE_ENABLED"])
- if self.CP.carFingerprint == CAR.XTRAIL:
+ if self.CP.carFingerprint in [CAR.ROGUE, CAR.XTRAIL]:
+ ret.seatbeltUnlatched = cp.vl["HUD"]["SEATBELT_DRIVER_LATCHED"] == 0
ret.cruiseState.available = bool(cp_cam.vl["PRO_PILOT"]["CRUISE_ON"])
elif self.CP.carFingerprint == CAR.LEAF:
+ ret.seatbeltUnlatched = cp.vl["SEATBELT"]["SEATBELT_DRIVER_LATCHED"] == 0
ret.cruiseState.available = bool(cp.vl["CRUISE_THROTTLE"]["CRUISE_AVAILABLE"])
- # TODO: Find mph/kph bit on XTRAIL until then, assume xtrail is kph.
- # Unable to change kph to mph on the xtrail, need a rogue to test it on
speed = cp_adas.vl["PROPILOT_HUD"]["SET_SPEED"]
if speed != 255:
- if self.CP.carFingerprint == CAR.XTRAIL:
- conversion = CV.KPH_TO_MS
- else:
+ if self.CP.carFingerprint == CAR.LEAF:
conversion = CV.MPH_TO_MS if cp.vl["HUD_SETTINGS"]["SPEED_MPH"] else CV.KPH_TO_MS
+ else:
+ conversion = CV.MPH_TO_MS if cp.vl["HUD"]["SPEED_MPH"] else CV.KPH_TO_MS
speed -= 1 # Speed on HUD is always 1 lower than actually sent on can bus
ret.cruiseState.speed = speed * conversion
ret.steeringTorque = cp.vl["STEER_TORQUE_SENSOR"]["STEER_TORQUE_DRIVER"]
- ret.steeringPressed = abs(ret.steeringTorque) > STEER_THRESHOLD
+ self.steeringTorqueSamples.append(ret.steeringTorque)
+ # Filtering driver torque to prevent steeringPressed false positives
+ ret.steeringPressed = bool(abs(sum(self.steeringTorqueSamples) / TORQUE_SAMPLES) > STEER_THRESHOLD)
ret.steeringAngle = cp.vl["STEER_ANGLE_SENSOR"]["STEER_ANGLE"]
@@ -72,8 +77,6 @@ class CarState(CarStateBase):
cp.vl["DOORS_LIGHTS"]["DOOR_OPEN_FR"],
cp.vl["DOORS_LIGHTS"]["DOOR_OPEN_FL"]])
- ret.seatbeltUnlatched = cp.vl["SEATBELT"]["SEATBELT_DRIVER_LATCHED"] == 0
-
ret.espDisabled = bool(cp.vl["ESP"]["ESP_DISABLED"])
can_gear = int(cp.vl["GEARBOX"]["GEAR_SHIFTER"])
@@ -113,8 +116,6 @@ class CarState(CarStateBase):
("RIGHT_BLINKER", "LIGHTS", 0),
("LEFT_BLINKER", "LIGHTS", 0),
- ("SEATBELT_DRIVER_LATCHED", "SEATBELT", 0),
-
("ESP_DISABLED", "ESP", 0),
("GEAR_SHIFTER", "GEARBOX", 0),
@@ -129,12 +130,14 @@ class CarState(CarStateBase):
("DOORS_LIGHTS", 10),
]
- if CP.carFingerprint == CAR.XTRAIL:
+ if CP.carFingerprint in [CAR.ROGUE, CAR.XTRAIL]:
signals += [
("USER_BRAKE_PRESSED", "DOORS_LIGHTS", 1),
("BRAKE_LIGHT", "DOORS_LIGHTS", 1),
("GAS_PEDAL", "GAS_PEDAL", 0),
+ ("SEATBELT_DRIVER_LATCHED", "HUD", 0),
+ ("SPEED_MPH", "HUD", 0),
("PROPILOT_BUTTON", "CRUISE_THROTTLE", 0),
("CANCEL_BUTTON", "CRUISE_THROTTLE", 0),
@@ -163,6 +166,7 @@ class CarState(CarStateBase):
("GAS_PEDAL", "CRUISE_THROTTLE", 0),
("CRUISE_AVAILABLE", "CRUISE_THROTTLE", 0),
("SPEED_MPH", "HUD_SETTINGS", 0),
+ ("SEATBELT_DRIVER_LATCHED", "SEATBELT", 0),
# Copy other values, we use this to cancel
("CANCEL_SEATBELT", "CANCEL_MSG", 0),
@@ -271,7 +275,7 @@ class CarState(CarStateBase):
@staticmethod
def get_cam_can_parser(CP):
signals = []
- if CP.carFingerprint == CAR.XTRAIL:
+ if CP.carFingerprint in [CAR.ROGUE, CAR.XTRAIL]:
signals += [
("CRUISE_ON", "PRO_PILOT", 0),
]
diff --git a/selfdrive/car/nissan/interface.py b/selfdrive/car/nissan/interface.py
index 34aeb13e65..9c419c5a8f 100644
--- a/selfdrive/car/nissan/interface.py
+++ b/selfdrive/car/nissan/interface.py
@@ -14,7 +14,7 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 4.0
@staticmethod
- def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]):
+ def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay)
ret.carName = "nissan"
@@ -31,10 +31,10 @@ class CarInterface(CarInterfaceBase):
ret.lateralTuning.pid.kf = 0.00006
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.0], [0.0]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.01], [0.005]]
- ret.steerMaxBP = [0.] # m/s
+ ret.steerMaxBP = [0.] # m/s
ret.steerMaxV = [1.]
- if candidate == CAR.XTRAIL:
+ if candidate in [CAR.ROGUE, CAR.XTRAIL]:
ret.mass = 1610 + STD_CARGO_KG
ret.wheelbase = 2.705
ret.centerToFront = ret.wheelbase * 0.44
@@ -86,7 +86,7 @@ class CarInterface(CarInterfaceBase):
def apply(self, c):
can_sends = self.CC.update(c.enabled, self.CS, self.frame, c.actuators,
c.cruiseControl.cancel, c.hudControl.visualAlert,
- c.hudControl.leftLaneVisible,c.hudControl.rightLaneVisible,
+ c.hudControl.leftLaneVisible, c.hudControl.rightLaneVisible,
c.hudControl.leftLaneDepart, c.hudControl.rightLaneDepart)
self.frame += 1
return can_sends
diff --git a/selfdrive/car/nissan/values.py b/selfdrive/car/nissan/values.py
index 96777e5a44..0630a8cb94 100644
--- a/selfdrive/car/nissan/values.py
+++ b/selfdrive/car/nissan/values.py
@@ -1,3 +1,5 @@
+# flake8: noqa
+
from selfdrive.car import dbc_dict
STEER_THRESHOLD = 1.0
@@ -5,25 +7,32 @@ STEER_THRESHOLD = 1.0
class CAR:
XTRAIL = "NISSAN X-TRAIL 2017"
LEAF = "NISSAN LEAF 2018"
+ ROGUE = "NISSAN ROGUE 2019"
FINGERPRINTS = {
CAR.XTRAIL: [
{
- 2: 5, 42: 6, 346: 6, 347: 5, 348: 8, 349: 7, 361: 8, 386: 8, 389: 8, 397: 8, 398: 8, 403: 8, 520: 2, 523: 6, 548: 8, 645: 8, 658: 8, 665: 8, 666: 8, 674: 2, 682: 8, 683: 8, 689: 8, 723: 8, 758: 3, 768: 2, 783: 3, 851: 8, 855: 8, 1041: 8, 1055: 2, 1104: 4, 1105: 6, 1107: 4, 1108: 8, 1111: 4, 1227: 8, 1228: 8, 1247: 4, 1266: 8, 1273: 7, 1342: 1, 1376: 6, 1401: 8, 1474: 2, 1497: 3, 1821: 8, 1823: 8, 1837:8, 2015: 8, 2016: 8, 2024: 8
+ 2: 5, 42: 6, 346: 6, 347: 5, 348: 8, 349: 7, 361: 8, 386: 8, 389: 8, 397: 8, 398: 8, 403: 8, 520: 2, 523: 6, 548: 8, 645: 8, 658: 8, 665: 8, 666: 8, 674: 2, 682: 8, 683: 8, 689: 8, 723: 8, 758: 3, 768: 2, 783: 3, 851: 8, 855: 8, 1041: 8, 1055: 2, 1104: 4, 1105: 6, 1107: 4, 1108: 8, 1111: 4, 1227: 8, 1228: 8, 1247: 4, 1266: 8, 1273: 7, 1342: 1, 1376: 6, 1401: 8, 1474: 2, 1497: 3, 1821: 8, 1823: 8, 1837: 8, 2015: 8, 2016: 8, 2024: 8
},
{
- 2: 5, 42: 6, 346: 6, 347: 5, 348: 8, 349: 7, 361: 8, 386: 8, 389: 8, 397: 8, 398: 8, 403: 8, 520: 2, 523: 6, 527: 1, 548: 8, 637: 4, 645: 8, 658: 8, 665: 8, 666: 8, 674: 2, 682: 8, 683: 8, 689: 8, 723: 8, 758: 3, 768: 6, 783: 3, 851: 8, 855: 8, 1041: 8, 1055: 2, 1104: 4, 1105: 6, 1107: 4, 1108: 8, 1111: 4, 1227: 8, 1228: 8, 1247: 4, 1266: 8, 1273: 7, 1342: 1, 1376: 6, 1401: 8, 1474: 8, 1497: 3,1534: 6, 1792: 8, 1821: 8, 1823: 8, 1837: 8, 1872: 8, 1937: 8, 1953: 8, 1968: 8, 2015: 8, 2016: 8, 2024: 8
+ 2: 5, 42: 6, 346: 6, 347: 5, 348: 8, 349: 7, 361: 8, 386: 8, 389: 8, 397: 8, 398: 8, 403: 8, 520: 2, 523: 6, 527: 1, 548: 8, 637: 4, 645: 8, 658: 8, 665: 8, 666: 8, 674: 2, 682: 8, 683: 8, 689: 8, 723: 8, 758: 3, 768: 6, 783: 3, 851: 8, 855: 8, 1041: 8, 1055: 2, 1104: 4, 1105: 6, 1107: 4, 1108: 8, 1111: 4, 1227: 8, 1228: 8, 1247: 4, 1266: 8, 1273: 7, 1342: 1, 1376: 6, 1401: 8, 1474: 8, 1497: 3, 1534: 6, 1792: 8, 1821: 8, 1823: 8, 1837: 8, 1872: 8, 1937: 8, 1953: 8, 1968: 8, 2015: 8, 2016: 8, 2024: 8
},
],
CAR.LEAF: [
{
- 2: 5, 42: 6, 264: 3, 361: 8, 372: 8, 384: 8, 389: 8, 403: 8, 459: 7, 460: 4, 470: 8, 520: 1, 569: 8, 581: 8, 634: 7, 640: 8, 644: 8, 645: 8, 646: 5, 658: 8, 682: 8, 683: 8, 689: 8, 724: 6, 758: 3, 761: 2, 783: 3, 852: 8, 853: 8, 856: 8, 861: 8, 944: 1, 976: 6, 1008: 7, 1011: 7, 1057: 3, 1227: 8, 1228: 8, 1261: 5, 1342: 1, 1354: 8, 1361: 8, 1459: 8, 1477: 8, 1497: 3, 1549: 8, 1573: 6, 1821: 8, 1837: 8, 1856: 8, 1859: 8, 1861: 8, 1864: 8, 1874: 8, 1888: 8, 1891: 8, 1893: 8, 1906: 8, 1947: 8, 1949: 8, 1979: 8, 1981: 8, 2016: 8, 2017: 8, 2021: 8
+ 2: 5, 42: 6, 264: 3, 361: 8, 372: 8, 384: 8, 389: 8, 403: 8, 459: 7, 460: 4, 470: 8, 520: 1, 569: 8, 581: 8, 634: 7, 640: 8, 644: 8, 645: 8, 646: 5, 658: 8, 682: 8, 683: 8, 689: 8, 724: 6, 758: 3, 761: 2, 783: 3, 852: 8, 853: 8, 856: 8, 861: 8, 944: 1, 976: 6, 1008: 7, 1011: 7, 1057: 3, 1227: 8, 1228: 8, 1261: 5, 1342: 1, 1354: 8, 1361: 8, 1459: 8, 1477: 8, 1497: 3, 1549: 8, 1573: 6, 1821: 8, 1837: 8, 1856: 8, 1859: 8, 1861: 8, 1864: 8, 1874: 8, 1888: 8, 1891: 8, 1893: 8, 1906: 8, 1947: 8, 1949: 8, 1979: 8, 1981: 8, 2016: 8, 2017: 8, 2021: 8, 643: 5, 1792: 8, 1872: 8, 1937: 8, 1953: 8, 1968: 8, 1988: 8, 2000: 8, 2001: 8, 2004: 8, 2005: 8, 2015: 8
},
],
+ CAR.ROGUE: [
+ {
+ 2: 5, 42: 6, 346: 6, 347: 5, 348: 8, 361: 8, 386: 8, 389: 8, 397: 8, 398: 8, 403: 8, 520: 2, 523: 6, 548: 8, 634: 7, 643: 5, 645: 8, 658: 8, 665: 8, 666: 8, 674: 2, 682: 8, 683: 8, 689: 8, 723: 8, 758: 3, 772: 8, 773: 6, 774: 7, 775: 8, 776: 6, 777: 7, 778: 6, 783: 3, 851: 8, 855: 8, 1041: 8, 1042: 8, 1055: 2, 1104: 4, 1105: 6, 1107: 4, 1108: 8, 1110: 7, 1111: 7, 1227: 8, 1228: 8, 1247: 4, 1266: 8, 1273: 7, 1342: 1, 1376: 6, 1401: 8, 1474: 2, 1497: 3, 1534: 7, 1821: 8, 1823: 8, 1837: 8, 1839: 8
+ },
+ ]
}
DBC = {
CAR.XTRAIL: dbc_dict('nissan_x_trail_2017', None),
CAR.LEAF: dbc_dict('nissan_leaf_2018', None),
+ CAR.ROGUE: dbc_dict('nissan_x_trail_2017', None),
}
diff --git a/selfdrive/car/subaru/__init__.py b/selfdrive/car/subaru/__init__.py
index 8b13789179..e69de29bb2 100644
--- a/selfdrive/car/subaru/__init__.py
+++ b/selfdrive/car/subaru/__init__.py
@@ -1 +0,0 @@
-
diff --git a/selfdrive/car/subaru/carcontroller.py b/selfdrive/car/subaru/carcontroller.py
index 7f3fc3d84b..744fd0bcc9 100644
--- a/selfdrive/car/subaru/carcontroller.py
+++ b/selfdrive/car/subaru/carcontroller.py
@@ -1,7 +1,6 @@
-#from common.numpy_fast import clip
from selfdrive.car import apply_std_steer_torque_limits
from selfdrive.car.subaru import subarucan
-from selfdrive.car.subaru.values import DBC
+from selfdrive.car.subaru.values import DBC, PREGLOBAL_CARS
from opendbc.can.packer import CANPacker
@@ -16,56 +15,73 @@ class CarControllerParams():
self.STEER_DRIVER_FACTOR = 1 # from dbc
-
class CarController():
def __init__(self, dbc_name, CP, VM):
- self.lkas_active = False
self.apply_steer_last = 0
self.es_distance_cnt = -1
+ self.es_accel_cnt = -1
self.es_lkas_cnt = -1
+ self.fake_button_prev = 0
self.steer_rate_limited = False
- # Setup detection helper. Routes commands to
- # an appropriate CAN bus number.
self.params = CarControllerParams()
self.packer = CANPacker(DBC[CP.carFingerprint]['pt'])
def update(self, enabled, CS, frame, actuators, pcm_cancel_cmd, visual_alert, left_line, right_line):
- """ Controls thread """
-
- P = self.params
- # Send CAN commands.
can_sends = []
- ### STEER ###
+ # *** steering ***
+ if (frame % self.params.STEER_STEP) == 0:
- if (frame % P.STEER_STEP) == 0:
-
- final_steer = actuators.steer if enabled else 0.
- apply_steer = int(round(final_steer * P.STEER_MAX))
+ apply_steer = int(round(actuators.steer * self.params.STEER_MAX))
# limits due to driver torque
new_steer = int(round(apply_steer))
- apply_steer = apply_std_steer_torque_limits(new_steer, self.apply_steer_last, CS.out.steeringTorque, P)
+ apply_steer = apply_std_steer_torque_limits(new_steer, self.apply_steer_last, CS.out.steeringTorque, self.params)
self.steer_rate_limited = new_steer != apply_steer
- lkas_enabled = enabled
-
- if not lkas_enabled:
+ if not enabled:
apply_steer = 0
- can_sends.append(subarucan.create_steering_control(self.packer, apply_steer, frame, P.STEER_STEP))
+ if CS.CP.carFingerprint in PREGLOBAL_CARS:
+ can_sends.append(subarucan.create_preglobal_steering_control(self.packer, apply_steer, frame, self.params.STEER_STEP))
+ else:
+ can_sends.append(subarucan.create_steering_control(self.packer, apply_steer, frame, self.params.STEER_STEP))
self.apply_steer_last = apply_steer
- if self.es_distance_cnt != CS.es_distance_msg["Counter"]:
- can_sends.append(subarucan.create_es_distance(self.packer, CS.es_distance_msg, pcm_cancel_cmd))
- self.es_distance_cnt = CS.es_distance_msg["Counter"]
- if self.es_lkas_cnt != CS.es_lkas_msg["Counter"]:
- can_sends.append(subarucan.create_es_lkas(self.packer, CS.es_lkas_msg, visual_alert, left_line, right_line))
- self.es_lkas_cnt = CS.es_lkas_msg["Counter"]
+ # *** alerts and pcm cancel ***
+
+ if CS.CP.carFingerprint in PREGLOBAL_CARS:
+ if self.es_accel_cnt != CS.es_accel_msg["Counter"]:
+ # 1 = main, 2 = set shallow, 3 = set deep, 4 = resume shallow, 5 = resume deep
+ # disengage ACC when OP is disengaged
+ if pcm_cancel_cmd:
+ fake_button = 1
+ # turn main on if off and past start-up state
+ elif not CS.out.cruiseState.available and CS.ready:
+ fake_button = 1
+ else:
+ fake_button = CS.button
+
+ # unstick previous mocked button press
+ if fake_button == 1 and self.fake_button_prev == 1:
+ fake_button = 0
+ self.fake_button_prev = fake_button
+
+ can_sends.append(subarucan.create_es_throttle_control(self.packer, fake_button, CS.es_accel_msg))
+ self.es_accel_cnt = CS.es_accel_msg["Counter"]
+
+ else:
+ if self.es_distance_cnt != CS.es_distance_msg["Counter"]:
+ can_sends.append(subarucan.create_es_distance(self.packer, CS.es_distance_msg, pcm_cancel_cmd))
+ self.es_distance_cnt = CS.es_distance_msg["Counter"]
+
+ if self.es_lkas_cnt != CS.es_lkas_msg["Counter"]:
+ can_sends.append(subarucan.create_es_lkas(self.packer, CS.es_lkas_msg, visual_alert, left_line, right_line))
+ self.es_lkas_cnt = CS.es_lkas_msg["Counter"]
return can_sends
diff --git a/selfdrive/car/subaru/carstate.py b/selfdrive/car/subaru/carstate.py
index ebfbaaa39a..5b5e23599c 100644
--- a/selfdrive/car/subaru/carstate.py
+++ b/selfdrive/car/subaru/carstate.py
@@ -4,7 +4,7 @@ from opendbc.can.can_define import CANDefine
from selfdrive.config import Conversions as CV
from selfdrive.car.interfaces import CarStateBase
from opendbc.can.parser import CANParser
-from selfdrive.car.subaru.values import DBC, STEER_THRESHOLD
+from selfdrive.car.subaru.values import DBC, STEER_THRESHOLD, CAR, PREGLOBAL_CARS
class CarState(CarStateBase):
@@ -20,7 +20,10 @@ class CarState(CarStateBase):
ret.gas = cp.vl["Throttle"]['Throttle_Pedal'] / 255.
ret.gasPressed = ret.gas > 1e-5
- ret.brakePressed = cp.vl["Brake_Pedal"]['Brake_Pedal'] > 1e-5
+ if self.car_fingerprint in PREGLOBAL_CARS:
+ ret.brakePressed = cp.vl["Brake_Pedal"]['Brake_Pedal'] > 2
+ else:
+ ret.brakePressed = cp.vl["Brake_Pedal"]['Brake_Pedal'] > 1e-5
ret.brakeLights = ret.brakePressed
ret.wheelSpeeds.fl = cp.vl["Wheel_Speeds"]['FL'] * CV.KPH_TO_MS
@@ -38,6 +41,9 @@ class CarState(CarStateBase):
self.right_blinker_cnt = 50 if cp.vl["Dashlights"]['RIGHT_BLINKER'] else max(self.right_blinker_cnt - 1, 0)
ret.rightBlinker = self.right_blinker_cnt > 0
+ ret.leftBlindspot = (cp.vl["BSD_RCTA"]['L_ADJACENT'] == 1) or (cp.vl["BSD_RCTA"]['L_APPROACHING'] == 1)
+ ret.rightBlindspot = (cp.vl["BSD_RCTA"]['R_ADJACENT'] == 1) or (cp.vl["BSD_RCTA"]['R_APPROACHING'] == 1)
+
can_gear = int(cp.vl["Transmission"]['Gear'])
ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(can_gear, None))
@@ -48,18 +54,31 @@ class CarState(CarStateBase):
ret.cruiseState.enabled = cp.vl["CruiseControl"]['Cruise_Activated'] != 0
ret.cruiseState.available = cp.vl["CruiseControl"]['Cruise_On'] != 0
ret.cruiseState.speed = cp_cam.vl["ES_DashStatus"]['Cruise_Set_Speed'] * CV.KPH_TO_MS
- # 1 = imperial, 6 = metric
- if cp.vl["Dash_State"]['Units'] == 1:
+
+ # UDM Forester, Legacy: mph = 0
+ if self.car_fingerprint in [CAR.FORESTER_PREGLOBAL, CAR.LEGACY_PREGLOBAL] and cp.vl["Dash_State"]['Units'] == 0:
+ ret.cruiseState.speed *= CV.MPH_TO_KPH
+ # EDM Global: mph = 1, 2; All Outback: mph = 1, UDM Forester: mph = 7
+ elif self.car_fingerprint not in [CAR.FORESTER_PREGLOBAL, CAR.LEGACY_PREGLOBAL] and cp.vl["Dash_State"]['Units'] in [1, 2, 7]:
ret.cruiseState.speed *= CV.MPH_TO_KPH
ret.seatbeltUnlatched = cp.vl["Dashlights"]['SEATBELT_FL'] == 1
ret.doorOpen = any([cp.vl["BodyInfo"]['DOOR_OPEN_RR'],
- cp.vl["BodyInfo"]['DOOR_OPEN_RL'],
- cp.vl["BodyInfo"]['DOOR_OPEN_FR'],
- cp.vl["BodyInfo"]['DOOR_OPEN_FL']])
-
- self.es_distance_msg = copy.copy(cp_cam.vl["ES_Distance"])
- self.es_lkas_msg = copy.copy(cp_cam.vl["ES_LKAS_State"])
+ cp.vl["BodyInfo"]['DOOR_OPEN_RL'],
+ cp.vl["BodyInfo"]['DOOR_OPEN_FR'],
+ cp.vl["BodyInfo"]['DOOR_OPEN_FL']])
+
+ if self.car_fingerprint in PREGLOBAL_CARS:
+ ret.steerError = cp.vl["Steering_Torque"]["LKA_Lockout"] == 1
+ self.button = cp_cam.vl["ES_CruiseThrottle"]["Button"]
+ self.ready = not cp_cam.vl["ES_DashStatus"]["Not_Ready_Startup"]
+ self.es_accel_msg = copy.copy(cp_cam.vl["ES_CruiseThrottle"])
+ else:
+ ret.steerError = cp.vl["Steering_Torque"]['Steer_Error_1'] == 1
+ ret.steerWarning = cp.vl["Steering_Torque"]['Steer_Warning'] == 1
+ ret.cruiseState.nonAdaptive = cp_cam.vl["ES_DashStatus"]['Conventional_Cruise'] == 1
+ self.es_distance_msg = copy.copy(cp_cam.vl["ES_Distance"])
+ self.es_lkas_msg = copy.copy(cp_cam.vl["ES_LKAS_State"])
return ret
@@ -87,56 +106,129 @@ class CarState(CarStateBase):
("DOOR_OPEN_RL", "BodyInfo", 1),
("Units", "Dash_State", 1),
("Gear", "Transmission", 0),
+ ("L_ADJACENT", "BSD_RCTA", 0),
+ ("R_ADJACENT", "BSD_RCTA", 0),
+ ("L_APPROACHING", "BSD_RCTA", 0),
+ ("R_APPROACHING", "BSD_RCTA", 0),
]
checks = [
# sig_address, frequency
+ ("Throttle", 100),
("Dashlights", 10),
- ("CruiseControl", 20),
+ ("Brake_Pedal", 50),
("Wheel_Speeds", 50),
+ ("Transmission", 100),
("Steering_Torque", 50),
- ("BodyInfo", 10),
]
+ if CP.carFingerprint in PREGLOBAL_CARS:
+ signals += [
+ ("LKA_Lockout", "Steering_Torque", 0),
+ ]
+ else:
+ signals += [
+ ("Steer_Error_1", "Steering_Torque", 0),
+ ("Steer_Warning", "Steering_Torque", 0),
+ ]
+
+ checks += [
+ ("Dashlights", 10),
+ ("BodyInfo", 10),
+ ("CruiseControl", 20),
+ ]
+
+ if CP.carFingerprint == CAR.FORESTER_PREGLOBAL:
+ checks += [
+ ("Dashlights", 20),
+ ("BodyInfo", 1),
+ ("CruiseControl", 50),
+ ]
+
+ if CP.carFingerprint in [CAR.LEGACY_PREGLOBAL, CAR.OUTBACK_PREGLOBAL, CAR.OUTBACK_PREGLOBAL_2018]:
+ checks += [
+ ("Dashlights", 10),
+ ("CruiseControl", 50),
+ ]
+
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 0)
@staticmethod
def get_cam_can_parser(CP):
- signals = [
- ("Cruise_Set_Speed", "ES_DashStatus", 0),
-
- ("Counter", "ES_Distance", 0),
- ("Signal1", "ES_Distance", 0),
- ("Signal2", "ES_Distance", 0),
- ("Main", "ES_Distance", 0),
- ("Signal3", "ES_Distance", 0),
-
- ("Counter", "ES_LKAS_State", 0),
- ("Keep_Hands_On_Wheel", "ES_LKAS_State", 0),
- ("Empty_Box", "ES_LKAS_State", 0),
- ("Signal1", "ES_LKAS_State", 0),
- ("LKAS_ACTIVE", "ES_LKAS_State", 0),
- ("Signal2", "ES_LKAS_State", 0),
- ("Backward_Speed_Limit_Menu", "ES_LKAS_State", 0),
- ("LKAS_ENABLE_3", "ES_LKAS_State", 0),
- ("Signal3", "ES_LKAS_State", 0),
- ("LKAS_ENABLE_2", "ES_LKAS_State", 0),
- ("Signal4", "ES_LKAS_State", 0),
- ("LKAS_Left_Line_Visible", "ES_LKAS_State", 0),
- ("Signal6", "ES_LKAS_State", 0),
- ("LKAS_Right_Line_Visible", "ES_LKAS_State", 0),
- ("Signal7", "ES_LKAS_State", 0),
- ("FCW_Cont_Beep", "ES_LKAS_State", 0),
- ("FCW_Repeated_Beep", "ES_LKAS_State", 0),
- ("Throttle_Management_Activated", "ES_LKAS_State", 0),
- ("Traffic_light_Ahead", "ES_LKAS_State", 0),
- ("Right_Depart", "ES_LKAS_State", 0),
- ("Signal5", "ES_LKAS_State", 0),
-
- ]
-
- checks = [
- ("ES_DashStatus", 10),
- ]
+ if CP.carFingerprint in PREGLOBAL_CARS:
+ signals = [
+ ("Cruise_Set_Speed", "ES_DashStatus", 0),
+ ("Not_Ready_Startup", "ES_DashStatus", 0),
+
+ ("Throttle_Cruise", "ES_CruiseThrottle", 0),
+ ("Signal1", "ES_CruiseThrottle", 0),
+ ("Cruise_Activated", "ES_CruiseThrottle", 0),
+ ("Signal2", "ES_CruiseThrottle", 0),
+ ("Brake_On", "ES_CruiseThrottle", 0),
+ ("DistanceSwap", "ES_CruiseThrottle", 0),
+ ("Standstill", "ES_CruiseThrottle", 0),
+ ("Signal3", "ES_CruiseThrottle", 0),
+ ("CloseDistance", "ES_CruiseThrottle", 0),
+ ("Signal4", "ES_CruiseThrottle", 0),
+ ("Standstill_2", "ES_CruiseThrottle", 0),
+ ("ES_Error", "ES_CruiseThrottle", 0),
+ ("Signal5", "ES_CruiseThrottle", 0),
+ ("Counter", "ES_CruiseThrottle", 0),
+ ("Signal6", "ES_CruiseThrottle", 0),
+ ("Button", "ES_CruiseThrottle", 0),
+ ("Signal7", "ES_CruiseThrottle", 0),
+ ]
+
+ checks = [
+ ("ES_DashStatus", 20),
+ ("ES_CruiseThrottle", 20),
+ ]
+ else:
+ signals = [
+ ("Cruise_Set_Speed", "ES_DashStatus", 0),
+ ("Conventional_Cruise", "ES_DashStatus", 0),
+
+ ("Counter", "ES_Distance", 0),
+ ("Signal1", "ES_Distance", 0),
+ ("Cruise_Fault", "ES_Distance", 0),
+ ("Cruise_Throttle", "ES_Distance", 0),
+ ("Signal2", "ES_Distance", 0),
+ ("Car_Follow", "ES_Distance", 0),
+ ("Signal3", "ES_Distance", 0),
+ ("Cruise_Brake_Active", "ES_Distance", 0),
+ ("Distance_Swap", "ES_Distance", 0),
+ ("Cruise_EPB", "ES_Distance", 0),
+ ("Signal4", "ES_Distance", 0),
+ ("Close_Distance", "ES_Distance", 0),
+ ("Signal5", "ES_Distance", 0),
+ ("Cruise_Cancel", "ES_Distance", 0),
+ ("Cruise_Set", "ES_Distance", 0),
+ ("Cruise_Resume", "ES_Distance", 0),
+ ("Signal6", "ES_Distance", 0),
+
+ ("Counter", "ES_LKAS_State", 0),
+ ("Keep_Hands_On_Wheel", "ES_LKAS_State", 0),
+ ("Empty_Box", "ES_LKAS_State", 0),
+ ("Signal1", "ES_LKAS_State", 0),
+ ("LKAS_ACTIVE", "ES_LKAS_State", 0),
+ ("Signal2", "ES_LKAS_State", 0),
+ ("Backward_Speed_Limit_Menu", "ES_LKAS_State", 0),
+ ("LKAS_ENABLE_3", "ES_LKAS_State", 0),
+ ("LKAS_Left_Line_Light_Blink", "ES_LKAS_State", 0),
+ ("LKAS_ENABLE_2", "ES_LKAS_State", 0),
+ ("LKAS_Right_Line_Light_Blink", "ES_LKAS_State", 0),
+ ("LKAS_Left_Line_Visible", "ES_LKAS_State", 0),
+ ("LKAS_Left_Line_Green", "ES_LKAS_State", 0),
+ ("LKAS_Right_Line_Visible", "ES_LKAS_State", 0),
+ ("LKAS_Right_Line_Green", "ES_LKAS_State", 0),
+ ("LKAS_Alert", "ES_LKAS_State", 0),
+ ("Signal3", "ES_LKAS_State", 0),
+ ]
+
+ checks = [
+ ("ES_DashStatus", 10),
+ ("ES_Distance", 20),
+ ("ES_LKAS_State", 10),
+ ]
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2)
diff --git a/selfdrive/car/subaru/interface.py b/selfdrive/car/subaru/interface.py
index 328666d79c..6d65f64f3d 100644
--- a/selfdrive/car/subaru/interface.py
+++ b/selfdrive/car/subaru/interface.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
from cereal import car
-from selfdrive.car.subaru.values import CAR
+from selfdrive.car.subaru.values import CAR, PREGLOBAL_CARS
from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint
from selfdrive.car.interfaces import CarInterfaceBase
@@ -11,16 +11,22 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 4.0
@staticmethod
- def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]):
+ def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay)
ret.carName = "subaru"
ret.radarOffCan = True
- ret.safetyModel = car.CarParams.SafetyModel.subaru
+
+ if candidate in PREGLOBAL_CARS:
+ ret.safetyModel = car.CarParams.SafetyModel.subaruLegacy
+ else:
+ ret.safetyModel = car.CarParams.SafetyModel.subaru
# Subaru port is a community feature, since we don't own one to test
ret.communityFeature = True
+ ret.dashcamOnly = candidate in PREGLOBAL_CARS
+
# force openpilot to fake the stock camera, since car harness is not supported yet and old style giraffe (with switches)
# was never released
ret.enableCamera = True
@@ -28,7 +34,17 @@ class CarInterface(CarInterfaceBase):
ret.steerRateCost = 0.7
ret.steerLimitTimer = 0.4
- if candidate in [CAR.IMPREZA]:
+ if candidate == CAR.ASCENT:
+ ret.mass = 2031. + STD_CARGO_KG
+ ret.wheelbase = 2.89
+ ret.centerToFront = ret.wheelbase * 0.5
+ ret.steerRatio = 13.5
+ ret.steerActuatorDelay = 0.3 # end-to-end angle controller
+ ret.lateralTuning.pid.kf = 0.00003
+ ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 20.], [0., 20.]]
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.0025, 0.1], [0.00025, 0.01]]
+
+ if candidate == CAR.IMPREZA:
ret.mass = 1568. + STD_CARGO_KG
ret.wheelbase = 2.67
ret.centerToFront = ret.wheelbase * 0.5
@@ -38,6 +54,47 @@ class CarInterface(CarInterfaceBase):
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 20.], [0., 20.]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2, 0.3], [0.02, 0.03]]
+ if candidate == CAR.FORESTER:
+ ret.mass = 1568. + STD_CARGO_KG
+ ret.wheelbase = 2.67
+ ret.centerToFront = ret.wheelbase * 0.5
+ ret.steerRatio = 17 # learned, 14 stock
+ ret.steerActuatorDelay = 0.1
+ ret.lateralTuning.pid.kf = 0.000038
+ ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 14., 23.], [0., 14., 23.]]
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.01, 0.065, 0.2], [0.001, 0.015, 0.025]]
+
+ if candidate in [CAR.FORESTER_PREGLOBAL, CAR.OUTBACK_PREGLOBAL_2018]:
+ ret.safetyParam = 1 # Outback 2018-2019 and Forester have reversed driver torque signal
+ ret.mass = 1568 + STD_CARGO_KG
+ ret.wheelbase = 2.67
+ ret.centerToFront = ret.wheelbase * 0.5
+ ret.steerRatio = 20 # learned, 14 stock
+ ret.steerActuatorDelay = 0.1
+ ret.lateralTuning.pid.kf = 0.000039
+ ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 10., 20.], [0., 10., 20.]]
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.01, 0.05, 0.2], [0.003, 0.018, 0.025]]
+
+ if candidate == CAR.LEGACY_PREGLOBAL:
+ ret.mass = 1568 + STD_CARGO_KG
+ ret.wheelbase = 2.67
+ ret.centerToFront = ret.wheelbase * 0.5
+ ret.steerRatio = 12.5 # 14.5 stock
+ ret.steerActuatorDelay = 0.15
+ ret.lateralTuning.pid.kf = 0.00005
+ ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 20.], [0., 20.]]
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.1, 0.2], [0.01, 0.02]]
+
+ if candidate == CAR.OUTBACK_PREGLOBAL:
+ ret.mass = 1568 + STD_CARGO_KG
+ ret.wheelbase = 2.67
+ ret.centerToFront = ret.wheelbase * 0.5
+ ret.steerRatio = 20 # learned, 14 stock
+ ret.steerActuatorDelay = 0.1
+ ret.lateralTuning.pid.kf = 0.000039
+ ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 10., 20.], [0., 10., 20.]]
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.01, 0.05, 0.2], [0.003, 0.018, 0.025]]
+
# TODO: get actual value, for now starting with reasonable value for
# civic and scaling by mass and wheelbase
ret.rotationalInertia = scale_rot_inertia(ret.mass, ret.wheelbase)
@@ -58,11 +115,6 @@ class CarInterface(CarInterfaceBase):
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
ret.steeringRateLimited = self.CC.steer_rate_limited if self.CC is not None else False
- buttonEvents = []
- be = car.CarState.ButtonEvent.new_message()
- be.type = car.CarState.ButtonEvent.Type.accelCruise
- buttonEvents.append(be)
-
ret.events = self.create_common_events(ret).to_msg()
self.CS.out = ret.as_reader()
diff --git a/selfdrive/car/subaru/subarucan.py b/selfdrive/car/subaru/subarucan.py
index d0850afc9e..8249d36ba9 100644
--- a/selfdrive/car/subaru/subarucan.py
+++ b/selfdrive/car/subaru/subarucan.py
@@ -5,8 +5,7 @@ VisualAlert = car.CarControl.HUDControl.VisualAlert
def create_steering_control(packer, apply_steer, frame, steer_step):
- # counts from 0 to 15 then back to 0 + 16 for enable bit
- idx = ((frame // steer_step) % 16)
+ idx = (frame / steer_step) % 16
values = {
"Counter": idx,
@@ -24,7 +23,7 @@ def create_es_distance(packer, es_distance_msg, pcm_cancel_cmd):
values = copy.copy(es_distance_msg)
if pcm_cancel_cmd:
- values["Main"] = 1
+ values["Cruise_Cancel"] = 1
return packer.make_can_msg("ES_Distance", 0, values)
@@ -38,3 +37,31 @@ def create_es_lkas(packer, es_lkas_msg, visual_alert, left_line, right_line):
values["LKAS_Right_Line_Visible"] = int(right_line)
return packer.make_can_msg("ES_LKAS_State", 0, values)
+
+# *** Subaru Pre-global ***
+
+def subaru_preglobal_checksum(packer, values, addr):
+ dat = packer.make_can_msg(addr, 0, values)[2]
+ return (sum(dat[:7])) % 256
+
+def create_preglobal_steering_control(packer, apply_steer, frame, steer_step):
+
+ idx = (frame / steer_step) % 8
+
+ values = {
+ "Counter": idx,
+ "LKAS_Command": apply_steer,
+ "LKAS_Active": 1 if apply_steer != 0 else 0
+ }
+ values["Checksum"] = subaru_preglobal_checksum(packer, values, "ES_LKAS")
+
+ return packer.make_can_msg("ES_LKAS", 0, values)
+
+def create_es_throttle_control(packer, fake_button, es_accel_msg):
+
+ values = copy.copy(es_accel_msg)
+ values["Button"] = fake_button
+
+ values["Checksum"] = subaru_preglobal_checksum(packer, values, "ES_CruiseThrottle")
+
+ return packer.make_can_msg("ES_CruiseThrottle", 0, values)
diff --git a/selfdrive/car/subaru/values.py b/selfdrive/car/subaru/values.py
index b75fa9c386..8cbb6fe72d 100644
--- a/selfdrive/car/subaru/values.py
+++ b/selfdrive/car/subaru/values.py
@@ -1,22 +1,81 @@
+# flake8: noqa
+
from selfdrive.car import dbc_dict
from cereal import car
Ecu = car.CarParams.Ecu
class CAR:
+ ASCENT = "SUBARU ASCENT LIMITED 2019"
IMPREZA = "SUBARU IMPREZA LIMITED 2019"
+ FORESTER = "SUBARU FORESTER 2019"
+ FORESTER_PREGLOBAL = "SUBARU FORESTER 2017 - 2018"
+ LEGACY_PREGLOBAL = "SUBARU LEGACY 2015 - 2018"
+ OUTBACK_PREGLOBAL = "SUBARU OUTBACK 2015 - 2017"
+ OUTBACK_PREGLOBAL_2018 = "SUBARU OUTBACK 2018 - 2019"
FINGERPRINTS = {
+ CAR.ASCENT: [{
+ # SUBARU ASCENT LIMITED 2019
+ 2: 8, 64: 8, 65: 8, 72: 8, 73: 8, 280: 8, 281: 8, 290: 8, 312: 8, 313: 8, 314: 8, 315: 8, 316: 8, 326: 8, 544: 8, 545: 8, 546: 8, 552: 8, 554: 8, 557: 8, 576: 8, 577: 8, 722: 8, 801: 8, 802: 8, 805: 8, 808: 8, 811: 8, 816: 8, 826: 8, 837: 8, 838: 8, 839: 8, 842: 8, 912: 8, 915: 8, 940: 8, 1614: 8, 1617: 8, 1632: 8, 1650: 8, 1657: 8, 1658: 8, 1677: 8, 1722: 8, 1743: 8, 1759: 8, 1785: 5, 1786: 5, 1787: 5, 1788: 8
+ }],
CAR.IMPREZA: [{
+ # SUBARU IMPREZA LIMITED 2019
2: 8, 64: 8, 65: 8, 72: 8, 73: 8, 280: 8, 281: 8, 290: 8, 312: 8, 313: 8, 314: 8, 315: 8, 316: 8, 326: 8, 544: 8, 545: 8, 546: 8, 552: 8, 554: 8, 557: 8, 576: 8, 577: 8, 722: 8, 801: 8, 802: 8, 805: 8, 808: 8, 816: 8, 826: 8, 837: 8, 838: 8, 839: 8, 842: 8, 912: 8, 915: 8, 940: 8, 1614: 8, 1617: 8, 1632: 8, 1650: 8, 1657: 8, 1658: 8, 1677: 8, 1697: 8, 1722: 8, 1743: 8, 1759: 8, 1786: 5, 1787: 5, 1788: 8, 1809: 8, 1813: 8, 1817: 8, 1821: 8, 1840: 8, 1848: 8, 1924: 8, 1932: 8, 1952: 8, 1960: 8
},
- # Crosstrek 2018 (same platform as Impreza)
+ # SUBARU CROSSTREK 2018
+ {
+ 2: 8, 64: 8, 65: 8, 72: 8, 73: 8, 280: 8, 281: 8, 290: 8, 312: 8, 313: 8, 314: 8, 315: 8, 316: 8, 326: 8, 372: 8, 544: 8, 545: 8, 546: 8, 554: 8, 557: 8, 576: 8, 577: 8, 722: 8, 801: 8, 802: 8, 805: 8, 808: 8, 811: 8, 826: 8, 837: 8, 838: 8, 839: 8, 842: 8, 912: 8, 915: 8, 940: 8, 1614: 8, 1617: 8, 1632: 8, 1650: 8, 1657: 8, 1658: 8, 1677: 8, 1697: 8, 1759: 8, 1786: 5, 1787: 5, 1788: 8
+ }],
+ CAR.FORESTER: [{
+ # Forester Sport 2019
+ 2: 8, 64: 8, 65: 8, 72: 8, 73: 8, 280: 8, 281: 8, 282: 8, 312: 8, 313: 8, 314: 8, 315: 8, 316: 8, 326: 8, 372: 8, 552: 8, 557: 8, 576: 8, 577: 8, 722: 8, 808: 8, 811: 8, 816: 8, 826: 8, 837: 8, 838: 8, 839: 8, 842: 8, 912: 8, 915: 8, 940: 8, 1614: 8, 1617: 8, 1632: 8, 1650: 8, 1651: 8, 1657: 8, 1658: 8, 1677: 8, 1697: 8, 1698: 8, 1722: 8, 1743: 8, 1759: 8, 1787: 5, 1788: 8, 1809: 8, 1813: 8, 1817: 8, 1821: 8, 1840: 8, 1848: 8, 1924: 8, 1932: 8, 1952: 8, 1960: 8
+ },
+ # Forester 2019
+ {
+ 2: 8, 64: 8, 65: 8, 72: 8, 73: 8, 280: 8, 281: 8, 282: 8, 290: 8, 312: 8, 313: 8, 314: 8, 315: 8, 316: 8, 326: 8, 372: 8, 544: 8, 545: 8, 546: 8, 554: 8, 557: 8, 576: 8, 577: 8, 722: 8, 801: 8, 802: 8, 803: 8, 805: 8, 808: 8, 811: 8, 826: 8, 837: 8, 838: 8, 839: 8, 842: 8, 912: 8, 915: 8, 940: 8, 1614: 8, 1617: 8, 1632: 8, 1650: 8, 1651: 8, 1657: 8, 1658: 8, 1677: 8, 1722: 8, 1759: 8, 1787: 5, 1788: 8
+ }],
+ CAR.OUTBACK_PREGLOBAL: [{
+ # OUTBACK PREMIUM 2.5i 2015
+ 2: 8, 208: 8, 209: 4, 210: 8, 211: 7, 212: 8, 320: 8, 321: 8, 324: 8, 328: 8, 329: 8, 336: 2, 338: 8, 342: 8, 346: 8, 352: 8, 353: 8, 354: 8, 356: 8, 358: 8, 359: 8, 392: 8, 640: 8, 642: 8, 644: 8, 864: 8, 865: 8, 866: 8, 872: 8, 880: 8, 881: 8, 882: 8, 884: 8, 977: 8, 1632: 8, 1745: 8, 1786: 5, 1882: 8, 2015: 8, 2016: 8, 2024: 8, 604: 8, 885: 8, 1788: 8, 316: 8, 1614: 8, 1640: 8, 1657: 8, 1658: 8, 1672: 8, 1743: 8, 1785: 5, 1787: 5
+ },
+ # OUTBACK PREMIUM 3.6i 2015
+ {
+ 2: 8, 208: 8, 209: 4, 210: 8, 211: 7, 212: 8, 320: 8, 321: 8, 324: 8, 328: 8, 329: 8, 336: 2, 338: 8, 342: 8, 392: 8, 604: 8, 640: 8, 642: 8, 644: 8, 864: 8, 865: 8, 866: 8, 872: 8, 880: 8, 881: 8, 882: 8, 884: 8, 977: 8, 1632: 8, 1745: 8, 1779: 8, 1786: 5
+ },
+ # OUTBACK LIMITED 2.5i 2018
{
- 2: 8, 64: 8, 65: 8, 72: 8, 73: 8, 256: 8, 280: 8, 281: 8, 290: 8, 312: 8, 313: 8, 314: 8, 315: 8, 316: 8, 326: 8, 372: 8, 544: 8, 545: 8, 546: 8, 554: 8, 557: 8, 576: 8, 577: 8, 722: 8, 801: 8, 802: 8, 805: 8, 808: 8, 811: 8, 826: 8, 837: 8, 838: 8, 839: 8, 842: 8, 912: 8, 915: 8, 940: 8, 1614: 8, 1617: 8, 1632: 8, 1650: 8, 1657: 8, 1658: 8, 1677: 8, 1697: 8, 1759: 8, 1786: 5, 1787: 5, 1788: 8
+ 2: 8, 208: 8, 209: 4, 210: 8, 211: 7, 212: 8, 316: 8, 320: 8, 321: 8, 324: 8, 328: 8, 329: 8, 336: 2, 338: 8, 342: 8, 352: 8, 353: 8, 354: 8, 356: 8, 358: 8, 359: 8, 392: 8, 554: 8, 604: 8, 640: 8, 642: 8, 644: 8, 805: 8, 864: 8, 865: 8, 866: 8, 872: 8, 880: 8, 881: 8, 882: 8, 884: 8, 885: 8, 977: 8, 1614: 8, 1632: 8, 1657: 8, 1658: 8, 1672: 8, 1722: 8, 1736: 8, 1743: 8, 1745: 8, 1785: 5, 1786: 5, 1787: 5, 1788: 8
+ }],
+ CAR.OUTBACK_PREGLOBAL_2018: [{
+ # OUTBACK LIMITED 3.6R 2019
+ 2: 8, 208: 8, 209: 4, 210: 8, 211: 7, 212: 8, 316: 8, 320: 8, 321: 8, 324: 8, 328: 8, 329: 8, 336: 2, 338: 8, 342: 8, 352: 8, 353: 8, 354: 8, 356: 8, 358: 8, 359: 8, 392: 8, 554: 8, 604: 8, 640: 8, 642: 8, 644: 8, 805: 8, 864: 8, 865: 8, 866: 8, 872: 8, 880: 8, 881: 8, 882: 8, 884: 8, 885: 8, 886: 2, 977: 8, 1614: 8, 1632: 8, 1657: 8, 1658: 8, 1672: 8, 1736: 8, 1743: 8, 1745: 8, 1785: 5, 1786: 5, 1787: 5, 1788: 8, 1862: 8, 1870: 8, 1920: 8, 1927: 8, 1928: 8, 1935: 8, 1968: 8, 1976: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8
+ }],
+ CAR.FORESTER_PREGLOBAL: [{
+ # FORESTER PREMIUM 2.5i 2017
+ 2: 8, 112: 8, 117: 8, 128: 8, 208: 8, 209: 4, 210: 8, 211: 7, 212: 8, 320: 8, 321: 8, 324: 8, 328: 8, 329: 8, 336: 2, 338: 8, 340: 7, 342: 8, 352: 8, 353: 8, 354: 8, 355: 8, 356: 8, 554: 8, 604: 8, 640: 8, 641: 8, 642: 8, 805: 8, 864: 8, 865: 8, 866: 8, 872: 8, 880: 8, 881: 8, 882: 8, 884: 8, 885: 8, 886: 1, 888: 8, 977: 8, 1398: 8, 1632: 8, 1743: 8, 1744: 8, 1745: 8, 1785: 5, 1786: 5, 1787: 5, 1788: 8, 1882: 8, 1895: 8, 1903: 8, 1986: 8, 1994: 8, 2015: 8, 2016: 8, 2024: 8, 644:8, 890:8, 1736:8
+ }],
+ CAR.LEGACY_PREGLOBAL: [{
+ # LEGACY 2.5i 2017
+ 2: 8, 208: 8, 209: 4, 210: 8, 211: 7, 212: 8, 320: 8, 321: 8, 324: 8, 328: 8, 329: 8, 336: 2, 338: 8, 342: 8, 392: 8, 604: 8, 640: 8, 642: 8, 864: 8, 865: 8, 866: 8, 872: 8, 880: 8, 881: 8, 882: 8, 884: 8, 885: 8, 977: 8, 1632: 8, 1640: 8, 1736: 8, 1745: 8, 1785: 5, 1786: 5, 1787: 5, 1788: 8, 352: 8, 353: 8, 354: 8, 356: 8, 358: 8, 359: 8, 644: 8
+ },
+ # LEGACY 2018
+ {
+ 2: 8, 208: 8, 209: 4, 210: 8, 211: 7, 212: 8, 316: 8, 320: 8, 321: 8, 324: 8, 328: 8, 329: 8, 336: 2, 338: 8, 342: 8, 392: 8, 604: 8, 640: 8, 642: 8, 864: 8, 865: 8, 866: 8, 872: 8, 880: 8, 881: 8, 882: 8, 884: 8, 885: 8, 977: 8, 1614: 8, 1632: 8, 1640: 8, 1657: 8, 1658: 8, 1672: 8, 1722: 8, 1743: 8, 1745: 8, 1778: 8, 1785: 5, 1786: 5, 1787: 5, 1788: 8, 2015: 8, 2016: 8, 2024: 8
+ },
+ # LEGACY 2018
+ {
+ 2: 8, 208: 8, 209: 4, 210: 8, 211: 7, 212: 8, 316: 8, 320: 8, 321: 8, 324: 8, 328: 8, 329: 8, 336: 2, 338: 8, 342: 8, 352: 8, 353: 8, 354: 8, 356: 8, 358: 8, 359: 8, 392: 8, 554: 8, 604: 8, 640: 8, 642: 8, 805: 8, 864: 8, 865: 8, 866: 8, 872: 8, 880: 8, 881: 8, 882: 8, 884: 8, 885: 8, 977: 8, 1614: 8, 1632: 8, 1640: 8, 1657: 8, 1658: 8, 1672: 8, 1722: 8, 1743: 8, 1745: 8, 1785: 5, 1786: 5, 1787: 5, 1788: 8, 2015: 8, 2016: 8, 2024: 8
}],
}
STEER_THRESHOLD = {
+ CAR.ASCENT: 80,
CAR.IMPREZA: 80,
+ CAR.FORESTER: 80,
+ CAR.FORESTER_PREGLOBAL: 75,
+ CAR.LEGACY_PREGLOBAL: 75,
+ CAR.OUTBACK_PREGLOBAL: 75,
+ CAR.OUTBACK_PREGLOBAL_2018: 75,
}
ECU_FINGERPRINT = {
@@ -24,5 +83,13 @@ ECU_FINGERPRINT = {
}
DBC = {
- CAR.IMPREZA: dbc_dict('subaru_global_2017', None),
+ CAR.ASCENT: dbc_dict('subaru_global_2017_generated', None),
+ CAR.IMPREZA: dbc_dict('subaru_global_2017_generated', None),
+ CAR.FORESTER: dbc_dict('subaru_global_2017_generated', None),
+ CAR.FORESTER_PREGLOBAL: dbc_dict('subaru_forester_2017_generated', None),
+ CAR.LEGACY_PREGLOBAL: dbc_dict('subaru_outback_2015_generated', None),
+ CAR.OUTBACK_PREGLOBAL: dbc_dict('subaru_outback_2015_generated', None),
+ CAR.OUTBACK_PREGLOBAL_2018: dbc_dict('subaru_outback_2019_generated', None),
}
+
+PREGLOBAL_CARS = [CAR.FORESTER_PREGLOBAL, CAR.LEGACY_PREGLOBAL, CAR.OUTBACK_PREGLOBAL, CAR.OUTBACK_PREGLOBAL_2018]
diff --git a/selfdrive/car/tests/test_car_interfaces.py b/selfdrive/car/tests/test_car_interfaces.py
index f320e0be29..069d5af00b 100755
--- a/selfdrive/car/tests/test_car_interfaces.py
+++ b/selfdrive/car/tests/test_car_interfaces.py
@@ -13,6 +13,7 @@ class TestCarInterfaces(unittest.TestCase):
all_cars = all_known_cars()
for car_name in all_cars:
+ print(car_name)
fingerprint = FINGERPRINTS[car_name][0]
CarInterface, CarController, CarState = interfaces[car_name]
@@ -30,6 +31,17 @@ class TestCarInterfaces(unittest.TestCase):
assert car_params
assert car_interface
+ self.assertGreater(car_params.mass, 1)
+ self.assertGreater(car_params.steerRateCost, 1e-3)
+
+ tuning = car_params.lateralTuning.which()
+ if tuning == 'pid':
+ self.assertTrue(len(car_params.lateralTuning.pid.kpV))
+ elif tuning == 'lqr':
+ self.assertTrue(len(car_params.lateralTuning.lqr.a))
+ elif tuning == 'indi':
+ self.assertGreater(car_params.lateralTuning.indi.outerLoopGain, 1e-3)
+
# Run car interface
CC = car.CarControl.new_message()
for _ in range(10):
@@ -51,7 +63,7 @@ class TestCarInterfaces(unittest.TestCase):
# Run radar interface once
radar_interface.update([])
- if hasattr(radar_interface, '_update') and hasattr(radar_interface, 'trigger_msg'):
+ if not car_params.radarOffCan and hasattr(radar_interface, '_update') and hasattr(radar_interface, 'trigger_msg'):
radar_interface._update([radar_interface.trigger_msg])
if __name__ == "__main__":
diff --git a/selfdrive/car/tests/test_fw_fingerprint.py b/selfdrive/car/tests/test_fw_fingerprint.py
index ff07f9fd7d..a9050e2373 100755
--- a/selfdrive/car/tests/test_fw_fingerprint.py
+++ b/selfdrive/car/tests/test_fw_fingerprint.py
@@ -1,18 +1,24 @@
#!/usr/bin/env python3
+import random
import unittest
+from itertools import product
+from parameterized import parameterized
+
from cereal import car
+from selfdrive.car.fingerprints import FW_VERSIONS
from selfdrive.car.fw_versions import match_fw_to_car
from selfdrive.car.toyota.values import CAR as TOYOTA
CarFw = car.CarParams.CarFw
Ecu = car.CarParams.Ecu
+ECU_NAME = {v: k for k, v in Ecu.schema.enumerants.items()}
class TestFwFingerprint(unittest.TestCase):
def assertFingerprints(self, candidates, expected):
candidates = list(candidates)
self.assertEqual(len(candidates), 1)
- self.assertEqual(candidates[0], TOYOTA.RAV4_TSS2)
+ self.assertEqual(candidates[0], expected)
def test_rav4_tss2(self):
CP = car.CarParams.new_message()
@@ -41,6 +47,45 @@ class TestFwFingerprint(unittest.TestCase):
self.assertFingerprints(match_fw_to_car(CP.carFw), TOYOTA.RAV4_TSS2)
+ @parameterized.expand([(k, v) for k, v in FW_VERSIONS.items()])
+ def test_fw_fingerprint_all(self, car_model, ecus):
+ # TODO: this is too slow, so don't run for now
+ return
+
+ ecu_fw_lists = [] # pylint: disable=W0101
+ for ecu, fw_versions in ecus.items():
+ ecu_name, addr, sub_addr = ecu
+ ecu_fw_lists.append([])
+ for fw in fw_versions:
+ ecu_fw_lists[-1].append({"ecu": ecu_name, "fwVersion": fw, "address": addr,
+ "subAddress": 0 if sub_addr is None else sub_addr})
+ CP = car.CarParams.new_message()
+ for car_fw in product(*ecu_fw_lists):
+ CP.carFw = car_fw
+ self.assertFingerprints(match_fw_to_car(CP.carFw), car_model)
+
+ @parameterized.expand([(k, v) for k, v in FW_VERSIONS.items()])
+ def test_fw_fingerprint(self, car_model, ecus):
+ CP = car.CarParams.new_message()
+ for _ in range(20):
+ fw = []
+ for ecu, fw_versions in ecus.items():
+ ecu_name, addr, sub_addr = ecu
+ fw.append({"ecu": ecu_name, "fwVersion": random.choice(fw_versions),
+ "address": addr, "subAddress": 0 if sub_addr is None else sub_addr})
+ CP.carFw = fw
+ self.assertFingerprints(match_fw_to_car(CP.carFw), car_model)
+
+ def test_no_duplicate_fw_versions(self):
+ passed = True
+ for car_model, ecus in FW_VERSIONS.items():
+ for ecu, ecu_fw in ecus.items():
+ duplicates = set([fw for fw in ecu_fw if ecu_fw.count(fw) > 1])
+ if len(duplicates):
+ print(car_model, ECU_NAME[ecu[0]], duplicates)
+ passed = False
+
+ self.assertTrue(passed, "Duplicate FW versions found")
if __name__ == "__main__":
unittest.main()
diff --git a/selfdrive/car/toyota/carcontroller.py b/selfdrive/car/toyota/carcontroller.py
index 0346801c0d..96e25013ea 100644
--- a/selfdrive/car/toyota/carcontroller.py
+++ b/selfdrive/car/toyota/carcontroller.py
@@ -12,7 +12,7 @@ VisualAlert = car.CarControl.HUDControl.VisualAlert
# Accel limits
ACCEL_HYST_GAP = 0.02 # don't change accel command for small oscilalitons within this value
ACCEL_MAX = 1.5 # 1.5 m/s2
-ACCEL_MIN = -3.0 # 3 m/s2
+ACCEL_MIN = -3.0 # 3 m/s2
ACCEL_SCALE = max(ACCEL_MAX, -ACCEL_MIN)
def accel_hysteresis(accel, accel_steady, enabled):
@@ -42,8 +42,10 @@ class CarController():
self.steer_rate_limited = False
self.fake_ecus = set()
- if CP.enableCamera: self.fake_ecus.add(Ecu.fwdCamera)
- if CP.enableDsu: self.fake_ecus.add(Ecu.dsu)
+ if CP.enableCamera:
+ self.fake_ecus.add(Ecu.fwdCamera)
+ if CP.enableDsu:
+ self.fake_ecus.add(Ecu.dsu)
self.packer = CANPacker(dbc_name)
diff --git a/selfdrive/car/toyota/carstate.py b/selfdrive/car/toyota/carstate.py
index c9970beadb..4cf84904e7 100644
--- a/selfdrive/car/toyota/carstate.py
+++ b/selfdrive/car/toyota/carstate.py
@@ -90,6 +90,8 @@ class CarState(CarStateBase):
else:
ret.cruiseState.standstill = self.pcm_acc_status == 7
ret.cruiseState.enabled = bool(cp.vl["PCM_CRUISE"]['CRUISE_ACTIVE'])
+ # TODO: CRUISE_STATE is a 4 bit signal, find any other non-adaptive cruise states
+ ret.cruiseState.nonAdaptive = cp.vl["PCM_CRUISE"]['CRUISE_STATE'] in [5]
if self.CP.carFingerprint == CAR.PRIUS:
ret.genericToggle = cp.vl["AUTOPARK_STATUS"]['STATE'] != 0
@@ -102,8 +104,8 @@ class CarState(CarStateBase):
self.steer_state = cp.vl["EPS_STATUS"]['LKA_STATE']
if self.CP.carFingerprint in TSS2_CAR:
- ret.leftBlindspot = cp.vl["BSM"]['L_ADJACENT'] == 1
- ret.rightBlindspot = cp.vl["BSM"]['R_ADJACENT'] == 1
+ ret.leftBlindspot = (cp.vl["BSM"]['L_ADJACENT'] == 1) or (cp.vl["BSM"]['L_APPROACHING'] == 1)
+ ret.rightBlindspot = (cp.vl["BSM"]['R_ADJACENT'] == 1) or (cp.vl["BSM"]['R_APPROACHING'] == 1)
return ret
@@ -160,7 +162,6 @@ class CarState(CarStateBase):
signals.append(("LOW_SPEED_LOCKOUT", "PCM_CRUISE_2", 0))
checks.append(("PCM_CRUISE_2", 33))
-
if CP.carFingerprint == CAR.PRIUS:
signals += [("STATE", "AUTOPARK_STATUS", 0)]
@@ -172,16 +173,23 @@ class CarState(CarStateBase):
if CP.carFingerprint in TSS2_CAR:
signals += [("L_ADJACENT", "BSM", 0)]
+ signals += [("L_APPROACHING", "BSM", 0)]
signals += [("R_ADJACENT", "BSM", 0)]
+ signals += [("R_APPROACHING", "BSM", 0)]
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 0)
@staticmethod
def get_cam_can_parser(CP):
- signals = [("FORCE", "PRE_COLLISION", 0), ("PRECOLLISION_ACTIVE", "PRE_COLLISION", 0)]
+ signals = [
+ ("FORCE", "PRE_COLLISION", 0),
+ ("PRECOLLISION_ACTIVE", "PRE_COLLISION", 0)
+ ]
# use steering message to check if panda is connected to frc
- checks = [("STEERING_LKA", 42)]
+ checks = [
+ ("STEERING_LKA", 42)
+ ]
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2)
diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py
index 84fe1b8b3a..e31eaee4ff 100755
--- a/selfdrive/car/toyota/interface.py
+++ b/selfdrive/car/toyota/interface.py
@@ -14,7 +14,7 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 3.0
@staticmethod
- def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]):
+ def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]): # pylint: disable=dangerous-default-value
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay)
ret.carName = "toyota"
@@ -23,7 +23,7 @@ class CarInterface(CarInterfaceBase):
ret.steerActuatorDelay = 0.12 # Default delay, Prius has larger delay
ret.steerLimitTimer = 0.4
- if candidate not in [CAR.PRIUS, CAR.RAV4, CAR.RAV4H]: # These cars use LQR/INDI
+ if candidate not in [CAR.PRIUS, CAR.RAV4, CAR.RAV4H]: # These cars use LQR/INDI
ret.lateralTuning.init('pid')
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
@@ -101,6 +101,16 @@ class CarInterface(CarInterfaceBase):
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.1]]
ret.lateralTuning.pid.kf = 0.00007818594
+ elif candidate == CAR.LEXUS_RXH_TSS2:
+ stop_and_go = True
+ ret.safetyParam = 73
+ ret.wheelbase = 2.79
+ ret.steerRatio = 16.0 # 14.8 is spec end-to-end
+ tire_stiffness_factor = 0.444 # not optimized yet
+ ret.mass = 4481.0 * CV.LB_TO_KG + STD_CARGO_KG # mean between min and max
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.15]]
+ ret.lateralTuning.pid.kf = 0.00007818594
+
elif candidate in [CAR.CHR, CAR.CHRH]:
stop_and_go = True
ret.safetyParam = 73
@@ -117,7 +127,7 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 2.82448
ret.steerRatio = 13.7
tire_stiffness_factor = 0.7933
- ret.mass = 3400. * CV.LB_TO_KG + STD_CARGO_KG #mean between normal and hybrid
+ ret.mass = 3400. * CV.LB_TO_KG + STD_CARGO_KG # mean between normal and hybrid
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.1]]
ret.lateralTuning.pid.kf = 0.00006
@@ -137,7 +147,7 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 2.78
ret.steerRatio = 16.0
tire_stiffness_factor = 0.8
- ret.mass = 4607. * CV.LB_TO_KG + STD_CARGO_KG #mean between normal and hybrid limited
+ ret.mass = 4607. * CV.LB_TO_KG + STD_CARGO_KG # mean between normal and hybrid limited
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.18], [0.015]] # community tuning
ret.lateralTuning.pid.kf = 0.00012 # community tuning
@@ -145,7 +155,7 @@ class CarInterface(CarInterfaceBase):
stop_and_go = False
ret.safetyParam = 73
ret.wheelbase = 2.82
- ret.steerRatio = 14.8 #Found at https://pressroom.toyota.com/releases/2016+avalon+product+specs.download
+ ret.steerRatio = 14.8 # Found at https://pressroom.toyota.com/releases/2016+avalon+product+specs.download
tire_stiffness_factor = 0.7983
ret.mass = 3505. * CV.LB_TO_KG + STD_CARGO_KG # mean between normal and hybrid
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.17], [0.03]]
@@ -161,6 +171,12 @@ class CarInterface(CarInterfaceBase):
ret.mass = 3370. * CV.LB_TO_KG + STD_CARGO_KG
ret.lateralTuning.pid.kf = 0.00004
+ for fw in car_fw:
+ if fw.ecu == "eps" and fw.fwVersion == b"8965B42170\x00\x00\x00\x00\x00\x00":
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.1]]
+ ret.lateralTuning.pid.kf = 0.00007818594
+ break
+
elif candidate == CAR.RAV4H_TSS2:
stop_and_go = True
ret.safetyParam = 73
@@ -171,6 +187,12 @@ class CarInterface(CarInterfaceBase):
ret.mass = 3800. * CV.LB_TO_KG + STD_CARGO_KG
ret.lateralTuning.pid.kf = 0.00004
+ for fw in car_fw:
+ if fw.ecu == "eps" and fw.fwVersion == b"8965B42170\x00\x00\x00\x00\x00\x00":
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.1]]
+ ret.lateralTuning.pid.kf = 0.00007818594
+ break
+
elif candidate in [CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2]:
stop_and_go = True
ret.safetyParam = 73
@@ -185,7 +207,7 @@ class CarInterface(CarInterfaceBase):
stop_and_go = True
ret.safetyParam = 73
ret.wheelbase = 2.8702
- ret.steerRatio = 16.0 # not optimized
+ ret.steerRatio = 16.0 # not optimized
tire_stiffness_factor = 0.444 # not optimized yet
ret.mass = 3704. * CV.LB_TO_KG + STD_CARGO_KG
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.1]]
@@ -226,7 +248,7 @@ class CarInterface(CarInterfaceBase):
ret.safetyParam = 73
ret.wheelbase = 2.66
ret.steerRatio = 14.7
- tire_stiffness_factor = 0.444 # not optimized yet
+ tire_stiffness_factor = 0.444 # not optimized yet
ret.mass = 4070 * CV.LB_TO_KG + STD_CARGO_KG
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.1]]
ret.lateralTuning.pid.kf = 0.00006
@@ -291,7 +313,6 @@ class CarInterface(CarInterfaceBase):
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
ret.steeringRateLimited = self.CC.steer_rate_limited if self.CC is not None else False
- ret.buttonEvents = []
# events
events = self.create_common_events(ret)
@@ -301,7 +322,7 @@ class CarInterface(CarInterfaceBase):
if self.CS.low_speed_lockout and self.CP.openpilotLongitudinalControl:
events.add(EventName.lowSpeedLockout)
if ret.vEgo < self.CP.minEnableSpeed and self.CP.openpilotLongitudinalControl:
- events.add(EventName.speedTooLow)
+ events.add(EventName.belowEngageSpeed)
if c.actuators.gas > 0.1:
# some margin on the actuator to not false trigger cancellation while stopping
events.add(EventName.speedTooLow)
diff --git a/selfdrive/car/toyota/radar_interface.py b/selfdrive/car/toyota/radar_interface.py
index 12387d489f..a7d2ec37bb 100755
--- a/selfdrive/car/toyota/radar_interface.py
+++ b/selfdrive/car/toyota/radar_interface.py
@@ -1,14 +1,10 @@
#!/usr/bin/env python3
-import os
-import time
from opendbc.can.parser import CANParser
from cereal import car
from selfdrive.car.toyota.values import NO_DSU_CAR, DBC, TSS2_CAR
from selfdrive.car.interfaces import RadarInterfaceBase
def _create_radar_can_parser(car_fingerprint):
- dbc_f = DBC[car_fingerprint]['radar']
-
if car_fingerprint in TSS2_CAR:
RADAR_A_MSGS = list(range(0x180, 0x190))
RADAR_B_MSGS = list(range(0x190, 0x1a0))
@@ -26,7 +22,7 @@ def _create_radar_can_parser(car_fingerprint):
checks = list(zip(RADAR_A_MSGS + RADAR_B_MSGS, [20]*(msg_a_n + msg_b_n)))
- return CANParser(os.path.splitext(dbc_f)[0], signals, checks, 1)
+ return CANParser(DBC[car_fingerprint]['radar'], signals, checks, 1)
class RadarInterface(RadarInterfaceBase):
def __init__(self, CP):
@@ -53,8 +49,7 @@ class RadarInterface(RadarInterfaceBase):
def update(self, can_strings):
if self.no_radar:
- time.sleep(self.radar_ts)
- return car.RadarData.new_message()
+ return super().update(None)
vls = self.rcp.update_strings(can_strings)
self.updated_messages.update(vls)
@@ -62,7 +57,7 @@ class RadarInterface(RadarInterfaceBase):
if self.trigger_msg not in self.updated_messages:
return None
- rr = self._update(self.updated_messages)
+ rr = self._update(self.updated_messages)
self.updated_messages.clear()
return rr
@@ -78,12 +73,12 @@ class RadarInterface(RadarInterfaceBase):
if ii in self.RADAR_A_MSGS:
cpt = self.rcp.vl[ii]
- if cpt['LONG_DIST'] >=255 or cpt['NEW_TRACK']:
+ if cpt['LONG_DIST'] >= 255 or cpt['NEW_TRACK']:
self.valid_cnt[ii] = 0 # reset counter
if cpt['VALID'] and cpt['LONG_DIST'] < 255:
self.valid_cnt[ii] += 1
else:
- self.valid_cnt[ii] = max(self.valid_cnt[ii] -1, 0)
+ self.valid_cnt[ii] = max(self.valid_cnt[ii] - 1, 0)
score = self.rcp.vl[ii+16]['SCORE']
# print ii, self.valid_cnt[ii], score, cpt['VALID'], cpt['LONG_DIST'], cpt['LAT_DIST']
diff --git a/selfdrive/car/toyota/toyotacan.py b/selfdrive/car/toyota/toyotacan.py
index bdd84e7128..93176b359c 100644
--- a/selfdrive/car/toyota/toyotacan.py
+++ b/selfdrive/car/toyota/toyotacan.py
@@ -36,7 +36,7 @@ def create_accel_command(packer, accel, pcm_cancel, standstill_req, lead):
"DISTANCE": 0,
"MINI_CAR": lead,
"SET_ME_X3": 3,
- "SET_ME_1": 1,
+ "PERMIT_BRAKING": 1,
"RELEASE_STANDSTILL": not standstill_req,
"CANCEL_REQ": pcm_cancel,
}
diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py
index d5d759ca37..f6d0c184f2 100644
--- a/selfdrive/car/toyota/values.py
+++ b/selfdrive/car/toyota/values.py
@@ -1,3 +1,5 @@
+# flake8: noqa
+
from selfdrive.car import dbc_dict
from cereal import car
Ecu = car.CarParams.Ecu
@@ -17,6 +19,7 @@ class CAR:
LEXUS_RX = "LEXUS RX 350 2016"
LEXUS_RXH = "LEXUS RX HYBRID 2017"
LEXUS_RX_TSS2 = "LEXUS RX350 2020"
+ LEXUS_RXH_TSS2 = "LEXUS RX450 HYBRID 2020"
CHR = "TOYOTA C-HR 2018"
CHRH = "TOYOTA C-HR HYBRID 2018"
CAMRY = "TOYOTA CAMRY 2018"
@@ -68,188 +71,193 @@ ECU_FINGERPRINT = {
FINGERPRINTS = {
CAR.RAV4: [{
- 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 512: 6, 513: 6, 547: 8, 548: 8, 552: 4, 562: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 767:4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 4, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1008: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1596: 8, 1597: 8, 1600: 8, 1656: 8, 1664: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2024: 8
+ 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 512: 6, 513: 6, 547: 8, 548: 8, 552: 4, 562: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 767: 4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 4, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1008: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1596: 8, 1597: 8, 1600: 8, 1656: 8, 1664: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2024: 8
}],
CAR.RAV4H: [{
- 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 296: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 547: 8, 548: 8, 550: 8, 552: 4, 560: 7, 562: 4, 581: 5, 608: 8, 610: 5, 643: 7, 705: 8, 713: 8, 725: 2, 740: 5, 767:4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1008: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1212: 8, 1227: 8, 1228: 8, 1232: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1596: 8, 1597: 8, 1600: 8, 1656: 8, 1664: 8, 1728: 8, 1745: 8, 1779: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 296: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 547: 8, 548: 8, 550: 8, 552: 4, 560: 7, 562: 4, 581: 5, 608: 8, 610: 5, 643: 7, 705: 8, 713: 8, 725: 2, 740: 5, 767: 4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1008: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1212: 8, 1227: 8, 1228: 8, 1232: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1596: 8, 1597: 8, 1600: 8, 1656: 8, 1664: 8, 1728: 8, 1745: 8, 1779: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
# Chinese RAV4
{
- 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 512: 6, 513: 6, 547: 8, 548: 8, 552: 4, 562: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 830: 7, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 921: 8, 922: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1008: 2, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1207: 8, 1227: 8, 1235: 8, 1263: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1596: 8, 1597: 8, 1600: 8, 1664: 8, 1728: 8, 1745: 8, 1779: 8
+ 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 512: 6, 513: 6, 547: 8, 548: 8, 552: 4, 562: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 742: 8, 743: 8, 767: 4, 800: 8, 830: 7, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 921: 8, 922: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1008: 2, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1207: 8, 1227: 8, 1235: 8, 1263: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1596: 8, 1597: 8, 1600: 8, 1664: 8, 1728: 8, 1745: 8, 1779: 8
}],
CAR.PRIUS: [{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 512: 6, 513: 6, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 814: 8, 824: 2, 829: 2, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 869: 7, 870: 7, 871: 2,898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 974: 8, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1083: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1175: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 512: 6, 513: 6, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767: 4, 800: 8, 810: 2, 814: 8, 824: 2, 829: 2, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 974: 8, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1083: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1175: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
#2019 LE
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 814: 8, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1083: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1175: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767: 4, 800: 8, 810: 2, 814: 8, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1083: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1175: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
# 2020 Prius Prime LE
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 740: 5, 742: 8, 743: 8, 764: 8, 767:4, 800: 8, 810: 2, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 974: 8, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1235: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1649: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 740: 5, 742: 8, 743: 8, 764: 8, 767: 4, 800: 8, 810: 2, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 974: 8, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1235: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1649: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
#2020 Prius Prime Limited
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 814: 8, 824: 2, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 974: 8, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1083: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1175: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1649: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2024: 8, 2026: 8, 2027: 8, 2029: 8, 2030: 8, 2031: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767: 4, 800: 8, 810: 2, 814: 8, 824: 2, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 974: 8, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1083: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1175: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1649: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2024: 8, 2026: 8, 2027: 8, 2029: 8, 2030: 8, 2031: 8
},
#2020 Central Europe Prime
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 740: 5, 742: 8, 743: 8, 764: 8, 767:4, 800: 8, 810: 2, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 8, 974: 8, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 740: 5, 742: 8, 743: 8, 764: 8, 767: 4, 800: 8, 810: 2, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 8, 974: 8, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8
},
#2017 German Prius
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296:8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8,740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 814: 8, 829: 2, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1077: 8, 1082: 8, 1083: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1175: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1777: 8, 1779: 8, 1792: 8, 1767:4, 1863:8, 1904: 8, 1912: 8, 1984: 8, 1988: 8, 1990: 8, 1992: 8, 1996:8, 1998: 8, 2002: 8, 2010: 8, 2015: 8, 2016: 8, 2018: 8, 2024: 8, 2026: 8, 2030: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767: 4, 800: 8, 810: 2, 814: 8, 829: 2, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1077: 8, 1082: 8, 1083: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1175: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1777: 8, 1779: 8, 1792: 8, 1767: 4, 1863: 8, 1904: 8, 1912: 8, 1984: 8, 1988: 8, 1990: 8, 1992: 8, 1996: 8, 1998: 8, 2002: 8, 2010: 8, 2015: 8, 2016: 8, 2018: 8, 2024: 8, 2026: 8, 2030: 8
}],
#Corolla w/ added Pedal Support (512L and 513L)
CAR.COROLLA: [{
- 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 512: 6, 513: 6, 547: 8, 548: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 767:4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 2, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 4, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1196: 8, 1227: 8, 1235: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1596: 8, 1597: 8, 1600: 8, 1664: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2016: 8, 2017: 8, 2018: 8, 2019: 8, 2020: 8, 2021: 8, 2022: 8, 2023: 8, 2024: 8
+ 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 512: 6, 513: 6, 547: 8, 548: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 767: 4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 2, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 4, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1196: 8, 1227: 8, 1235: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1596: 8, 1597: 8, 1600: 8, 1664: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2016: 8, 2017: 8, 2018: 8, 2019: 8, 2020: 8, 2021: 8, 2022: 8, 2023: 8, 2024: 8
}],
CAR.LEXUS_RX: [{
# 2016 Lexus RX 350
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 812: 3, 818: 8, 819: 8, 820: 8, 821: 8, 822: 8, 830: 7, 835: 8, 836: 8, 845: 5, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1349: 8, 1350: 8, 1351: 8, 1413: 8, 1414: 8, 1415: 8, 1416: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 742: 8, 743: 8, 767: 4, 800: 8, 810: 2, 812: 3, 818: 8, 819: 8, 820: 8, 821: 8, 822: 8, 830: 7, 835: 8, 836: 8, 845: 5, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1349: 8, 1350: 8, 1351: 8, 1413: 8, 1414: 8, 1415: 8, 1416: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
},
# 2017 Lexus RX 350
{
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 5, 643: 7, 658: 8, 705: 8, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 812: 3, 814: 8, 818: 8, 819: 8, 820: 8, 821: 8, 822: 8, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1349: 8, 1350: 8, 1351: 8, 1413: 8, 1414: 8, 1415: 8, 1416: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 5, 643: 7, 658: 8, 705: 8, 740: 5, 742: 8, 743: 8, 767: 4, 800: 8, 810: 2, 812: 3, 814: 8, 818: 8, 819: 8, 820: 8, 821: 8, 822: 8, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1349: 8, 1350: 8, 1351: 8, 1413: 8, 1414: 8, 1415: 8, 1416: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
}],
CAR.LEXUS_RXH: [{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 512: 6, 513:6, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 5, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 812: 3, 814: 8, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 6, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1071: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1595: 8, 1777: 8, 1779: 8, 1808: 8, 1810: 8, 1816: 8, 1818: 8, 1840: 8, 1848: 8, 1904: 8, 1912: 8, 1940: 8, 1941: 8, 1948: 8, 1949: 8, 1952: 8, 1956: 8, 1960: 8, 1964: 8, 1986: 8, 1990: 8, 1994: 8, 1998: 8, 2004: 8, 2012: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 512: 6, 513: 6, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 5, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767: 4, 800: 8, 810: 2, 812: 3, 814: 8, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 6, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1071: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1595: 8, 1777: 8, 1779: 8, 1808: 8, 1810: 8, 1816: 8, 1818: 8, 1840: 8, 1848: 8, 1904: 8, 1912: 8, 1940: 8, 1941: 8, 1948: 8, 1949: 8, 1952: 8, 1956: 8, 1960: 8, 1964: 8, 1986: 8, 1990: 8, 1994: 8, 1998: 8, 2004: 8, 2012: 8
},
# RX450HL
# TODO: get proper fingerprint in stock mode
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 512: 6, 513: 6, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 5, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 812: 3, 814: 8, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 6, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1056: 8, 1057: 8, 1059: 1, 1063: 8, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 512: 6, 513: 6, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 5, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767: 4, 800: 8, 810: 2, 812: 3, 814: 8, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 6, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1056: 8, 1057: 8, 1059: 1, 1063: 8, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
# RX540H 2019 with color hud
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 512: 6, 513: 6, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 5, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 812: 3, 814: 8, 818: 8, 819: 8, 820: 8, 821: 8, 822: 8, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 6, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1063: 8, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1349: 8, 1350: 8, 1351: 8, 1413: 8, 1414: 8, 1415: 8, 1416: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1777: 8, 1779: 8, 1808: 8, 1810: 8, 1816: 8, 1818: 8, 1904: 8, 1912: 8, 1952: 8, 1960: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 512: 6, 513: 6, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 5, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767: 4, 800: 8, 810: 2, 812: 3, 814: 8, 818: 8, 819: 8, 820: 8, 821: 8, 822: 8, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 6, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1063: 8, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1349: 8, 1350: 8, 1351: 8, 1413: 8, 1414: 8, 1415: 8, 1416: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1777: 8, 1779: 8, 1808: 8, 1810: 8, 1816: 8, 1818: 8, 1904: 8, 1912: 8, 1952: 8, 1960: 8, 1990: 8, 1998: 8
},
# 2017 RX 450h
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 5, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 744: 8, 767:4, 800: 8, 810: 2, 812: 3, 814: 8, 818: 8, 819: 8, 820: 8, 821: 8, 822: 8, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 6, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1071: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1349: 8, 1350: 8, 1351: 8, 1413: 8, 1414: 8, 1415: 8, 1416: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1595: 8, 1745: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 5, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 744: 8, 767: 4, 800: 8, 810: 2, 812: 3, 814: 8, 818: 8, 819: 8, 820: 8, 821: 8, 822: 8, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 6, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1071: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1349: 8, 1350: 8, 1351: 8, 1413: 8, 1414: 8, 1415: 8, 1416: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1595: 8, 1745: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
}],
CAR.LEXUS_RX_TSS2: [
# 2020 Lexus RX 350
{
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 740: 5, 742: 8, 743: 8, 764: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 824: 8, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 891: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 987: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1076: 8, 1077: 8,1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594:8, 1595: 8, 1600: 8, 1649: 8, 1775: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1816: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 740: 5, 742: 8, 743: 8, 764: 8, 765: 8, 767: 4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 824: 8, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 891: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 987: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594: 8, 1595: 8, 1600: 8, 1649: 8, 1775: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1816: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
+ }],
+ CAR.LEXUS_RXH_TSS2: [
+ # 2020 Lexus RX 450h
+ {
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 401: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 744: 8, 764: 8, 765: 8, 800: 8, 810: 2, 812: 3, 814: 8, 818: 8, 822: 8, 824: 8, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 889: 8, 891: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 942: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 6, 987: 8, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1063: 8, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594: 8, 1595: 8, 1600: 8, 1649: 8, 1775: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1792: 8, 1808: 8, 1809: 8, 1810: 8, 1816: 8, 1818: 8, 1840: 8, 1848: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1937: 8, 1940: 8, 1941: 8, 1945: 8, 1948: 8, 1949: 8, 1952: 8, 1953: 8, 1956: 8, 1960: 8, 1961: 8, 1968: 8, 1976: 8, 1986: 8, 1990: 8, 1994: 8, 1998: 8, 2004: 8, 2012: 8, 2015: 8, 2016: 8, 2024: 8
}],
CAR.CHR: [{
- 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 705: 8, 740: 5, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 830: 7, 835: 8, 836: 8, 845: 5, 869: 7, 870: 7, 871: 2, 898: 8, 913: 8, 918: 8, 921: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 1014: 8, 1017: 8, 1020: 8, 1021: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1082: 8, 1083: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1175: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8
+ 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 705: 8, 740: 5, 767: 4, 800: 8, 810: 2, 812: 8, 814: 8, 830: 7, 835: 8, 836: 8, 845: 5, 869: 7, 870: 7, 871: 2, 898: 8, 913: 8, 918: 8, 921: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 1014: 8, 1017: 8, 1020: 8, 1021: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1082: 8, 1083: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1175: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8
}],
CAR.CHRH: [{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 829: 2, 830: 7, 835: 8, 836: 8, 845: 5, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1021: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1083: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1175: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 767: 4, 800: 8, 810: 2, 812: 8, 814: 8, 829: 2, 830: 7, 835: 8, 836: 8, 845: 5, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1021: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1083: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1175: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
}],
CAR.CAMRY: [
#XLE and LE
{
- 36: 8, 37: 8, 119: 6, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 871: 2, 888: 8, 889: 8, 891: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 983: 8, 984: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1412: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1816: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 119: 6, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767: 4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 871: 2, 888: 8, 889: 8, 891: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 983: 8, 984: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1412: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1816: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
#XSE and SE
# TODO: get proper fingerprint in stock mode
{
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 888: 8, 889: 8, 891: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 983: 8, 984: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1412: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1816: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767: 4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 888: 8, 889: 8, 891: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 983: 8, 984: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1412: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1816: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
{
# 2019 XSE
- 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 888: 8, 889: 8, 891: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 942: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 983: 8, 984: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1412: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1792: 8, 1767:4, 1808: 8, 1816: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1937: 8, 1945: 8, 1953: 8, 1961: 8, 1968: 8, 1976: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
+ 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767: 4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 888: 8, 889: 8, 891: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 942: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 983: 8, 984: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1412: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1792: 8, 1767: 4, 1808: 8, 1816: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1937: 8, 1945: 8, 1953: 8, 1961: 8, 1968: 8, 1976: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
}],
CAR.CAMRYH: [
#SE, LE and LE with Blindspot Monitor
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767:4, 800: 8, 810: 2, 812: 8, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 983: 8, 984: 8, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1810: 8, 1816: 8, 1818: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767: 4, 800: 8, 810: 2, 812: 8, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 983: 8, 984: 8, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1810: 8, 1816: 8, 1818: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
#SL
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767:4, 800: 8, 810: 2, 812: 8, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 871: 2, 888: 8, 889: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767: 4, 800: 8, 810: 2, 812: 8, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 871: 2, 888: 8, 889: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
#XLE
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 658: 8, 713: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 871: 2, 888: 8, 889: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 983: 8, 984: 8, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 658: 8, 713: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767: 4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 871: 2, 888: 8, 889: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 983: 8, 984: 8, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
}],
CAR.HIGHLANDER: [{
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 767:4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 921: 8, 922: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1008: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1207: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1984: 8, 1988: 8, 1992: 8, 1996: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 767: 4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 921: 8, 922: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1008: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1207: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1984: 8, 1988: 8, 1992: 8, 1996: 8, 1990: 8, 1998: 8
},
# 2019 Highlander XLE
{
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 767:4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 921: 8, 922: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1008: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1207: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 767: 4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 921: 8, 922: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1008: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1207: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
# 2017 Highlander Limited
{
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 767:4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 922: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1008: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1207: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 767: 4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 922: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1008: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1207: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
# 2018 Highlander Limited Platinum
{
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 767:4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 922: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1008: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1207: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1263: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1585: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1728: 8, 1745: 8, 1779: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1988: 8, 1990: 8, 1996: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 767: 4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 922: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1008: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1207: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1263: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1585: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1728: 8, 1745: 8, 1779: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1988: 8, 1990: 8, 1996: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
}],
CAR.HIGHLANDER_TSS2: [{
# 2020 highlander limited
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 355: 5, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 565: 8, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 824: 8, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 885: 8, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 987: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1816: 8, 1904: 8, 1912: 8, 1952: 8, 1960: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 355: 5, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 565: 8, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 765: 8, 767: 4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 824: 8, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 885: 8, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 987: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1816: 8, 1904: 8, 1912: 8, 1952: 8, 1960: 8, 1990: 8, 1998: 8
}],
CAR.HIGHLANDERH: [{
- 36: 8, 37: 8, 170: 8, 180: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 767:4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1212: 8, 1227: 8, 1232: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 170: 8, 180: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 767: 4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1212: 8, 1227: 8, 1232: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
{
# 2019 Highlander Hybrid Limited Platinum
- 36: 8, 37: 8, 170: 8, 180: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 767:4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1076: 8, 1077: 8, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1212: 8, 1227: 8, 1232: 8, 1235: 8, 1237: 8, 1263: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 170: 8, 180: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 767: 4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1076: 8, 1077: 8, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1212: 8, 1227: 8, 1232: 8, 1235: 8, 1237: 8, 1263: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
}],
CAR.HIGHLANDERH_TSS2: [{
36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 401: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 658: 8, 713: 8, 728: 8, 740: 5, 761: 8, 765: 8, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 881: 8, 885: 8, 891: 8, 896: 8, 898: 8, 918: 8, 942: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 971: 7, 975: 5, 987: 8, 993: 8, 1014: 8, 1017: 8, 1020: 8, 1059: 1, 1063: 8, 1071: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1552: 8, 1553: 8, 1556: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1745: 8
}],
CAR.AVALON: [{
- 36: 8, 37: 8, 170: 8, 180: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 547: 8, 550: 8, 552: 4, 562: 6, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 767:4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 905: 8, 911: 1, 916: 2, 921: 8, 933: 6, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 1005: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1200: 8, 1201: 8, 1202: 8, 1203: 8, 1206: 8, 1227: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1558: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1596: 8, 1597: 8, 1664: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 170: 8, 180: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 547: 8, 550: 8, 552: 4, 562: 6, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 767: 4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 905: 8, 911: 1, 916: 2, 921: 8, 933: 6, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 1005: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1200: 8, 1201: 8, 1202: 8, 1203: 8, 1206: 8, 1227: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1558: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1596: 8, 1597: 8, 1664: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
}],
CAR.RAV4_TSS2: [
# LE
{
- 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 355: 5, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 565: 8, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1076: 8, 1077: 8,1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1235: 8, 1279: 8, 1541: 8, 1552: 8, 1553:8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 355: 5, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 565: 8, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 767: 4, 800: 8, 810: 2, 812: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1076: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1235: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
# XLE, Limited, and AWD
{
- 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 565: 8, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 889: 8, 891: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 987: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1076: 8, 1077: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
+ 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 565: 8, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 767: 4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 889: 8, 891: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 987: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1076: 8, 1077: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
}],
CAR.COROLLA_TSS2: [
# hatch 2019+ and sedan 2020+
{
- 36: 8, 37: 8, 114: 5, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1235: 8, 1237: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1809: 8, 1816: 8, 1817: 8, 1840: 8, 1848: 8, 1904: 8, 1912: 8, 1940: 8, 1941: 8, 1948: 8, 1949: 8, 1952: 8, 1960: 8, 1981: 8, 1986: 8, 1990: 8, 1994: 8, 1998: 8, 2004: 8
+ 36: 8, 37: 8, 114: 5, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 767: 4, 800: 8, 810: 2, 812: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1235: 8, 1237: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1809: 8, 1816: 8, 1817: 8, 1840: 8, 1848: 8, 1904: 8, 1912: 8, 1940: 8, 1941: 8, 1948: 8, 1949: 8, 1952: 8, 1960: 8, 1981: 8, 1986: 8, 1990: 8, 1994: 8, 1998: 8, 2004: 8
}],
CAR.COROLLAH_TSS2: [
# 2019 Taiwan Altis Hybrid
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 401: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 765: 8, 767:4, 800: 8, 810: 2, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 885: 8, 896: 8, 898: 8, 918: 7, 921: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 987: 8, 993: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1082: 8, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1172: 8, 1235: 8, 1237: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1745: 8, 1775: 8, 1779: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 401: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 765: 8, 767: 4, 800: 8, 810: 2, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 885: 8, 896: 8, 898: 8, 918: 7, 921: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 987: 8, 993: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1082: 8, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1172: 8, 1235: 8, 1237: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1745: 8, 1775: 8, 1779: 8
},
# 2019 Chinese Levin Hybrid
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 401: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 885: 8, 896: 8, 898: 8, 921: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1172: 8, 1235: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1600: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 401: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 765: 8, 767: 4, 800: 8, 810: 2, 812: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 885: 8, 896: 8, 898: 8, 921: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1172: 8, 1235: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1600: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8
}
],
CAR.LEXUS_ES_TSS2: [{
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 824: 8, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 987: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1775: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8,
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 765: 8, 767: 4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 824: 8, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 987: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1775: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8,
}],
CAR.LEXUS_ESH_TSS2: [
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 401: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 658: 8, 713: 8, 728: 8, 740: 5, 742: 8, 743: 8, 744: 8, 761: 8, 764: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 987: 8, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1775: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 401: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 658: 8, 713: 8, 728: 8, 740: 5, 742: 8, 743: 8, 744: 8, 761: 8, 764: 8, 765: 8, 767: 4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 987: 8, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1775: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
}],
CAR.SIENNA: [
{
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 548: 8, 550: 8, 552: 4, 562: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 764: 8, 767:4, 800: 8, 824: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 888: 8, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 1, 918: 7, 921: 8, 933: 8, 944: 6, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1008: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1160: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1200: 8, 1201: 8, 1202: 8, 1203: 8, 1212: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1656: 8, 1664: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 548: 8, 550: 8, 552: 4, 562: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 764: 8, 767: 4, 800: 8, 824: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 888: 8, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 1, 918: 7, 921: 8, 933: 8, 944: 6, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1008: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1160: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1200: 8, 1201: 8, 1202: 8, 1203: 8, 1212: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1656: 8, 1664: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
# XLE AWD 2018
{
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 548: 8, 550: 8, 552: 4, 562: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 764: 8, 767:4, 800: 8, 824: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 1, 921: 8, 933: 8, 944: 6, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1008: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1160: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1200: 8, 1201: 8, 1202: 8, 1203: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1656: 8, 1664: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 548: 8, 550: 8, 552: 4, 562: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 764: 8, 767: 4, 800: 8, 824: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 1, 921: 8, 933: 8, 944: 6, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1008: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1160: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1200: 8, 1201: 8, 1202: 8, 1203: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1656: 8, 1664: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
}],
CAR.LEXUS_IS: [
# IS300 2018
{
- 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 400: 6, 426: 6, 452: 8, 464: 8, 466: 8, 467: 5, 544: 4, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 767:4, 800: 8, 836: 8, 845: 5, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 913: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1008: 2, 1009: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1168: 1, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1184: 8, 1185: 8, 1186: 8, 1187: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1208: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1584: 8, 1589: 8, 1590: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1648: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 400: 6, 426: 6, 452: 8, 464: 8, 466: 8, 467: 5, 544: 4, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 767: 4, 800: 8, 836: 8, 845: 5, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 913: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1008: 2, 1009: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1168: 1, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1184: 8, 1185: 8, 1186: 8, 1187: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1208: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1584: 8, 1589: 8, 1590: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1648: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
# IS300H 2017
{
- 36: 8, 37: 8, 170: 8, 180: 8, 295: 8, 296: 8, 400: 6, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 767:4, 800: 8, 836: 8, 845: 5, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 913: 8, 916: 3, 918: 7, 921: 7, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1009: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1168: 1, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1187: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1208: 8, 1212: 8, 1227: 8, 1232: 8, 1235: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 170: 8, 180: 8, 295: 8, 296: 8, 400: 6, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 767: 4, 800: 8, 836: 8, 845: 5, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 913: 8, 916: 3, 918: 7, 921: 7, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1009: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1168: 1, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1187: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1208: 8, 1212: 8, 1227: 8, 1232: 8, 1235: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
}],
CAR.RAV4H_TSS2: [
#Hybrid Limited
{
- 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 401: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 658: 8, 713: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 889: 8, 891: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913:8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 987: 8, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1063: 8, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1810: 8, 1816: 8, 1818: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
+ 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 401: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 658: 8, 713: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 767: 4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 889: 8, 891: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 987: 8, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1063: 8, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1810: 8, 1816: 8, 1818: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
},
],
CAR.LEXUS_CTH: [{
@@ -261,32 +269,52 @@ FINGERPRINTS = {
}
# Don't use theses fingerprints for fingerprinting, they are still needed for ECU detection
-IGNORED_FINGERPRINTS = [CAR.RAV4H_TSS2, CAR.HIGHLANDERH_TSS2]
+IGNORED_FINGERPRINTS = [CAR.RAV4H_TSS2, CAR.HIGHLANDERH_TSS2, CAR.LEXUS_RXH_TSS2]
FW_VERSIONS = {
CAR.AVALON: {
(Ecu.esp, 0x7b0, None): [b'F152607060\x00\x00\x00\x00\x00\x00'],
- (Ecu.dsu, 0x791, None): [b'881510705200\x00\x00\x00\x00'],
+ (Ecu.dsu, 0x791, None): [
+ b'881510705200\x00\x00\x00\x00',
+ b'881510701300\x00\x00\x00\x00',
+ ],
(Ecu.eps, 0x7a1, None): [b'8965B41051\x00\x00\x00\x00\x00\x00'],
- (Ecu.engine, 0x7e0, None): [b'\x0230721200\x00\x00\x00\x00\x00\x00\x00\x00A0C01000\x00\x00\x00\x00\x00\x00\x00\x00'],
- (Ecu.fwdRadar, 0x750, 0xf): [b'8821F4702100\x00\x00\x00\x00'],
- (Ecu.fwdCamera, 0x750, 0x6d): [b'8646F0703000\x00\x00\x00\x00'],
+ (Ecu.engine, 0x7e0, None): [
+ b'\x0230721100\x00\x00\x00\x00\x00\x00\x00\x00A0C01000\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'\x0230721200\x00\x00\x00\x00\x00\x00\x00\x00A0C01000\x00\x00\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdRadar, 0x750, 0xf): [
+ b'8821F4702000\x00\x00\x00\x00',
+ b'8821F4702100\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdCamera, 0x750, 0x6d): [
+ b'8646F0701100\x00\x00\x00\x00',
+ b'8646F0703000\x00\x00\x00\x00',
+ ],
},
CAR.CAMRY: {
(Ecu.engine, 0x700, None): [
+ b'\x018966306L3100\x00\x00\x00\x00',
+ b'\x018966306L4200\x00\x00\x00\x00',
b'\x018966306L5200\x00\x00\x00\x00',
+ b'\x018966306Q3100\x00\x00\x00\x00',
+ b'\x018966306Q4000\x00\x00\x00\x00',
+ b'\x018966306Q4100\x00\x00\x00\x00',
+ b'\x018966333P3100\x00\x00\x00\x00',
+ b'\x018966333P3200\x00\x00\x00\x00',
b'\x018966333P4200\x00\x00\x00\x00',
b'\x018966333P4300\x00\x00\x00\x00',
b'\x018966333P4400\x00\x00\x00\x00',
b'\x018966333P4500\x00\x00\x00\x00',
b'\x018966333P4700\x00\x00\x00\x00',
+ b'\x018966333Q6000\x00\x00\x00\x00',
b'\x018966333Q6200\x00\x00\x00\x00',
- b'\x018966306Q4100\x00\x00\x00\x00',
],
(Ecu.dsu, 0x791, None): [
- b'8821F0607200 ',
+ b'8821F0601200 ',
b'8821F0601300 ',
b'8821F0603300 ',
+ b'8821F0607200 ',
b'8821F0608000 ',
],
(Ecu.esp, 0x7b0, None): [
@@ -301,6 +329,7 @@ FW_VERSIONS = {
b'8965B33580\x00\x00\x00\x00\x00\x00',
],
(Ecu.fwdRadar, 0x750, 0xf): [ # Same as 0x791
+ b'8821F0601200 ',
b'8821F0601300 ',
b'8821F0603300 ',
b'8821F0607200 ',
@@ -312,52 +341,100 @@ FW_VERSIONS = {
b'8646F0603400 ',
b'8646F0605000 ',
b'8646F0606000 ',
+ b'8646F0606100 ',
],
},
CAR.CAMRYH: {
(Ecu.engine, 0x700, None): [
+ b'\x018966333N4300\x00\x00\x00\x00',
+ b'\x018966333X0000\x00\x00\x00\x00',
b'\x028966306B2100\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00',
+ b'\x028966306B2300\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00',
+ b'\x028966306N8100\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00',
b'\x028966306N8200\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00',
+ b'\x028966306N8300\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00',
+ b'\x028966306N8400\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00',
b'\x028966306R5000\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00',
+ b'\x028966306R5000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00',
b'\x028966306R6000\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00',
+ b'\x028966306R6000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00',
+ b'\x028966306S0000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00',
b'\x028966306S0100\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00',
+ b'\x028966306S1100\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00',
],
(Ecu.esp, 0x7b0, None): [
+ b'F152633214\x00\x00\x00\x00\x00\x00',
+ b'F152633660\x00\x00\x00\x00\x00\x00',
b'F152633712\x00\x00\x00\x00\x00\x00',
b'F152633713\x00\x00\x00\x00\x00\x00',
b'F152633B51\x00\x00\x00\x00\x00\x00',
+ b'F152633B60\x00\x00\x00\x00\x00\x00',
],
(Ecu.dsu, 0x791, None): [
b'8821F0601200 ',
b'8821F0601300 ',
+ b'8821F0603400 ',
+ b'8821F0604200 ',
+ b'8821F0606200 ',
b'8821F0607200 ',
b'8821F0608000 ',
+ b'8821F0609000 ',
+ b'8821F0609100 ',
],
(Ecu.eps, 0x7a1, None): [
b'8965B33540\x00\x00\x00\x00\x00\x00',
+ b'8965B33542\x00\x00\x00\x00\x00\x00',
+ b'8965B33550\x00\x00\x00\x00\x00\x00',
+ b'8965B33551\x00\x00\x00\x00\x00\x00',
b'8965B33580\x00\x00\x00\x00\x00\x00',
+ b'8965B33581\x00\x00\x00\x00\x00\x00',
+ b'8965B33611\x00\x00\x00\x00\x00\x00',
+ b'8965B33621\x00\x00\x00\x00\x00\x00',
],
(Ecu.fwdRadar, 0x750, 0xf): [ # Same as 0x791
b'8821F0601200 ',
b'8821F0601300 ',
+ b'8821F0603400 ',
+ b'8821F0604200 ',
+ b'8821F0606200 ',
b'8821F0607200 ',
b'8821F0608000 ',
+ b'8821F0609000 ',
+ b'8821F0609100 ',
],
(Ecu.fwdCamera, 0x750, 0x6d): [
b'8646F0601200 ',
b'8646F0601300 ',
+ b'8646F0601400 ',
+ b'8646F0603500 ',
+ b'8646F0604100 ',
b'8646F0605000 ',
+ b'8646F0606000 ',
+ b'8646F0606100 ',
+ b'8646F0607000 ',
+ b'8646F0607100 ',
],
},
CAR.CHR: {
(Ecu.engine, 0x700, None): [
+ b'\x01896631017100\x00\x00\x00\x00',
+ b'\x01896631017200\x00\x00\x00\x00',
b'\x0189663F413100\x00\x00\x00\x00',
+ b'\x0189663F414100\x00\x00\x00\x00',
],
(Ecu.dsu, 0x791, None): [
+ b'8821F0W01000 ',
b'8821FF401600 ',
b'8821FF404100 ',
+ b'8821FF405100 ',
+ b'8821FF406000 ',
+ b'8821F0W01100 ',
],
(Ecu.esp, 0x7b0, None): [
+ b'F152610020\x00\x00\x00\x00\x00\x00',
+ b'F152610153\x00\x00\x00\x00\x00\x00',
+ b'F1526F4034\x00\x00\x00\x00\x00\x00',
+ b'F1526F4044\x00\x00\x00\x00\x00\x00',
b'F1526F4073\x00\x00\x00\x00\x00\x00',
b'F1526F4122\x00\x00\x00\x00\x00\x00',
],
@@ -366,24 +443,50 @@ FW_VERSIONS = {
b'8965B10040\x00\x00\x00\x00\x00\x00',
],
(Ecu.engine, 0x7e0, None): [
+ b'\x033F401100\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203102\x00\x00\x00\x00',
b'\x033F424000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203202\x00\x00\x00\x00',
+ b'\x0331024000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203302\x00\x00\x00\x00',
],
(Ecu.fwdRadar, 0x750, 0xf): [
+ b'8821F0W01000 ',
b'8821FF401600 ',
b'8821FF404100 ',
+ b'8821FF405100 ',
+ b'8821FF406000 ',
+ b'8821F0W01100 ',
],
(Ecu.fwdCamera, 0x750, 0x6d): [
b'8646FF401800 ',
b'8646FF404000 ',
+ b'8646FF406000 ',
],
},
CAR.CHRH: {
- (Ecu.engine, 0x700, None): [b'\x0289663F431000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00'],
- (Ecu.esp, 0x7b0, None): [b'F152610040\x00\x00\x00\x00\x00\x00'],
- (Ecu.dsu, 0x791, None): [b'8821FF407100 '],
- (Ecu.eps, 0x7a1, None): [b'8965B10050\x00\x00\x00\x00\x00\x00'],
- (Ecu.fwdRadar, 0x750, 0xf): [b'8821FF407100 '],
- (Ecu.fwdCamera, 0x750, 0x6d): [b'8646FF407000 '],
+ (Ecu.engine, 0x700, None): [
+ b'\x0289663F423000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
+ b'\x0289663F431000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
+ b'\x0189663F438000\x00\x00\x00\x00',
+ ],
+ (Ecu.esp, 0x7b0, None): [
+ b'F152610040\x00\x00\x00\x00\x00\x00',
+ b'F152610190\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.dsu, 0x791, None): [
+ b'8821FF404000 ',
+ b'8821FF407100 ',
+ ],
+ (Ecu.eps, 0x7a1, None): [
+ b'8965B10040\x00\x00\x00\x00\x00\x00',
+ b'8965B10050\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdRadar, 0x750, 0xf): [
+ b'8821FF404000 ',
+ b'8821FF407100 ',
+ ],
+ (Ecu.fwdCamera, 0x750, 0x6d): [
+ b'8646FF404000 ',
+ b'8646FF407000 ',
+ ],
},
CAR.COROLLA: {
(Ecu.engine, 0x7e0, None): [
@@ -425,11 +528,13 @@ FW_VERSIONS = {
b'\x01896630ZG5000\x00\x00\x00\x00',
b'\x01896630ZG5100\x00\x00\x00\x00',
b'\x01896630ZG5200\x00\x00\x00\x00',
+ b'\x01896630ZG5300\x00\x00\x00\x00',
b'\x01896630ZQ5000\x00\x00\x00\x00',
b'\x018966312L8000\x00\x00\x00\x00',
b'\x018966312P9000\x00\x00\x00\x00',
b'\x018966312P9100\x00\x00\x00\x00',
b'\x018966312P9200\x00\x00\x00\x00',
+ b'\x018966312R0100\x00\x00\x00\x00',
b'\x018966312R1000\x00\x00\x00\x00',
b'\x018966312R1100\x00\x00\x00\x00',
b'\x018966312R3100\x00\x00\x00\x00',
@@ -438,11 +543,13 @@ FW_VERSIONS = {
b'\x03312N6000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203202\x00\x00\x00\x00',
b'\x03312N6000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203302\x00\x00\x00\x00',
b'\x03312N6100\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203302\x00\x00\x00\x00',
+ b'\x03312N6100\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203402\x00\x00\x00\x00',
],
(Ecu.eps, 0x7a1, None): [
b'8965B12361\x00\x00\x00\x00\x00\x00',
b'\x018965B12350\x00\x00\x00\x00\x00\x00',
b'\x018965B12500\x00\x00\x00\x00\x00\x00',
+ b'\x018965B12520\x00\x00\x00\x00\x00\x00',
b'\x018965B12530\x00\x00\x00\x00\x00\x00',
],
(Ecu.esp, 0x7b0, None): [
@@ -450,8 +557,10 @@ FW_VERSIONS = {
b'\x01F152602280\x00\x00\x00\x00\x00\x00',
b'\x01F152602560\x00\x00\x00\x00\x00\x00',
b'\x01F152612641\x00\x00\x00\x00\x00\x00',
+ b'\x01F152612651\x00\x00\x00\x00\x00\x00',
b'\x01F152612B10\x00\x00\x00\x00\x00\x00',
b'\x01F152612B60\x00\x00\x00\x00\x00\x00',
+ b'\x01F152612B61\x00\x00\x00\x00\x00\x00',
b'\x01F152612B90\x00\x00\x00\x00\x00\x00',
],
(Ecu.fwdRadar, 0x750, 0xf): [
@@ -464,24 +573,28 @@ FW_VERSIONS = {
b'\x028646F12010D0\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00',
b'\x028646F1201100\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00',
b'\x028646F1201200\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00',
+ b'\x028646F1201300\x00\x00\x00\x008646G2601400\x00\x00\x00\x00',
b'\x028646F1202000\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
+ b'\x028646F1202100\x00\x00\x00\x008646G2601400\x00\x00\x00\x00',
],
},
CAR.COROLLAH_TSS2: {
(Ecu.engine, 0x700, None): [
+ b'\x01896630ZJ1000\x00\x00\x00\x00',
b'\x018966342M5000\x00\x00\x00\x00',
b'\x02896630ZQ3000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
b'\x02896630ZR2000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
b'\x028966312Q4000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
+ b'\x038966312L7000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF1205001\x00\x00\x00\x00',
b'\x038966312N1000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00',
],
(Ecu.eps, 0x7a1, None): [
b'8965B12361\x00\x00\x00\x00\x00\x00',
b'8965B12451\x00\x00\x00\x00\x00\x00',
- b'8965B42170\x00\x00\x00\x00\x00\x00',
b'\x018965B12350\x00\x00\x00\x00\x00\x00',
b'\x018965B12470\x00\x00\x00\x00\x00\x00',
b'\x018965B12500\x00\x00\x00\x00\x00\x00',
+ b'\x018965B12520\x00\x00\x00\x00\x00\x00',
b'\x018965B12530\x00\x00\x00\x00\x00\x00',
],
(Ecu.esp, 0x7b0, None): [
@@ -493,6 +606,7 @@ FW_VERSIONS = {
b'F152612840\x00\x00\x00\x00\x00\x00',
b'F152612A10\x00\x00\x00\x00\x00\x00',
b'F152642540\x00\x00\x00\x00\x00\x00',
+ b'F152612A00\x00\x00\x00\x00\x00\x00',
],
(Ecu.fwdRadar, 0x750, 0xf): [
b'\x018821F3301100\x00\x00\x00\x00',
@@ -502,19 +616,27 @@ FW_VERSIONS = {
],
(Ecu.fwdCamera, 0x750, 0x6d): [
b'\x028646F1201100\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00',
+ b'\x028646F1201300\x00\x00\x00\x008646G2601400\x00\x00\x00\x00',
b'\x028646F1202000\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
+ b'\x028646F1202100\x00\x00\x00\x008646G2601400\x00\x00\x00\x00',
b'\x028646F4203400\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
],
},
CAR.HIGHLANDER: {
(Ecu.engine, 0x700, None): [
+ b'\x01896630E09000\x00\x00\x00\x00',
b'\x01896630E43100\x00\x00\x00\x00',
+ b'\x01896630E43200\x00\x00\x00\x00',
+ b'\x01896630E44200\x00\x00\x00\x00',
+ b'\x01896630E45000\x00\x00\x00\x00',
+ b'\x01896630E45100\x00\x00\x00\x00',
b'\x01896630E45200\x00\x00\x00\x00',
+ b'\x01896630E74000\x00\x00\x00\x00',
+ b'\x01896630E76000\x00\x00\x00\x00',
b'\x01896630E83000\x00\x00\x00\x00',
b'\x01896630E84000\x00\x00\x00\x00',
b'\x01896630E85000\x00\x00\x00\x00',
b'\x01896630E88000\x00\x00\x00\x00',
- b'\x01896630E09000\x00\x00\x00\x00',
],
(Ecu.eps, 0x7a1, None): [
b'8965B48140\x00\x00\x00\x00\x00\x00',
@@ -536,32 +658,90 @@ FW_VERSIONS = {
],
},
CAR.HIGHLANDERH: {
- (Ecu.eps, 0x7a1, None): [b'8965B48160\x00\x00\x00\x00\x00\x00'],
- (Ecu.esp, 0x7b0, None): [b'F152648541\x00\x00\x00\x00\x00\x00'],
- (Ecu.engine, 0x7e0, None): [b'\x0230E40000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00'],
- (Ecu.fwdRadar, 0x750, 0xf): [b'8821F4702100\x00\x00\x00\x00'],
- (Ecu.fwdCamera, 0x750, 0x6d): [b'8646F0E01200\x00\x00\x00\x00'],
+ (Ecu.eps, 0x7a1, None): [
+ b'8965B48160\x00\x00\x00\x00\x00\x00'
+ ],
+ (Ecu.esp, 0x7b0, None): [
+ b'F152648541\x00\x00\x00\x00\x00\x00',
+ b'F152648542\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.engine, 0x7e0, None): [
+ b'\x0230E40000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'\x0230EA2000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdRadar, 0x750, 0xf): [
+ b'8821F4702100\x00\x00\x00\x00',
+ b'8821F4702300\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdCamera, 0x750, 0x6d): [
+ b'8646F0E01200\x00\x00\x00\x00',
+ b'8646F0E01300\x00\x00\x00\x00',
+ ],
+ },
+ CAR.HIGHLANDER_TSS2: {
+ (Ecu.eps, 0x7a1, None): [
+ b'8965B48241\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.esp, 0x7b0, None): [
+ b'\x01F15260E051\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.engine, 0x700, None): [
+ b'\x01896630E64100\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdRadar, 0x750, 0xf): [
+ b'\x018821F3301400\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdCamera, 0x750, 0x6d): [
+ b'\x028646F0E02100\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
+ ],
},
CAR.HIGHLANDERH_TSS2: {
- (Ecu.eps, 0x7a1, None): [b'8965B48241\x00\x00\x00\x00\x00\x00',],
- (Ecu.esp, 0x7b0, None): [b'\x01F15264872300\x00\x00\x00\x00',],
- (Ecu.engine, 0x700, None): [b'\x02896630E66000\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00',],
- (Ecu.fwdRadar, 0x750, 0xf): [b'\x018821F3301400\x00\x00\x00\x00',],
- (Ecu.fwdCamera, 0x750, 0x6d): [b'\x028646F0E02100\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',],
+ (Ecu.eps, 0x7a1, None): [
+ b'8965B48241\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.esp, 0x7b0, None): [
+ b'\x01F15264872300\x00\x00\x00\x00',
+ ],
+ (Ecu.engine, 0x700, None): [
+ b'\x02896630E66000\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdRadar, 0x750, 0xf): [
+ b'\x018821F3301400\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdCamera, 0x750, 0x6d): [
+ b'\x028646F0E02100\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
+ ],
},
CAR.LEXUS_IS: {
- (Ecu.engine, 0x700, None): [b'\x018966353Q2300\x00\x00\x00\x00'],
- (Ecu.esp, 0x7b0, None): [b'F152653330\x00\x00\x00\x00\x00\x00'],
- (Ecu.dsu, 0x791, None): [b'881515306400\x00\x00\x00\x00'],
- (Ecu.eps, 0x7a1, None): [b'8965B53271\x00\x00\x00\x00\x00\x00'],
- (Ecu.fwdRadar, 0x750, 0xf): [b'8821F4702300\x00\x00\x00\x00'],
- (Ecu.fwdCamera, 0x750, 0x6d): [b'8646F5301400\x00\x00\x00\x00'],
+ (Ecu.engine, 0x700, None): [
+ b'\x018966353M7100\x00\x00\x00\x00',
+ b'\x018966353Q2300\x00\x00\x00\x00',
+ b'\x018966353R8100\x00\x00\x00\x00',
+ ],
+ (Ecu.esp, 0x7b0, None): [
+ b'F152653330\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.dsu, 0x791, None): [
+ b'881515306400\x00\x00\x00\x00',
+ b'881515306500\x00\x00\x00\x00',
+ ],
+ (Ecu.eps, 0x7a1, None): [
+ b'8965B53271\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdRadar, 0x750, 0xf): [
+ b'8821F4702300\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdCamera, 0x750, 0x6d): [
+ b'8646F5301400\x00\x00\x00\x00',
+ ],
},
CAR.PRIUS: {
(Ecu.engine, 0x700, None): [
b'\x02896634761000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
b'\x02896634761100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
+ b'\x02896634761200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
b'\x02896634763000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
+ b'\x02896634765000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
b'\x02896634769100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
b'\x02896634774000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
b'\x02896634774100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
@@ -569,20 +749,27 @@ FW_VERSIONS = {
b'\x02896634782000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
b'\x02896634784000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
b'\x028966347A5000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
- b'\x03896634759200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701004\x00\x00\x00\x00',
+ b'\x028966347A8000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
+ b'\x02896634765100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
+ b'\x03896634759100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701003\x00\x00\x00\x00',
b'\x03896634759200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701003\x00\x00\x00\x00',
+ b'\x03896634759200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701004\x00\x00\x00\x00',
b'\x03896634759300\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701004\x00\x00\x00\x00',
b'\x03896634760000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701002\x00\x00\x00\x00',
+ b'\x03896634760000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701003\x00\x00\x00\x00',
b'\x03896634760100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701003\x00\x00\x00\x00',
b'\x03896634760200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701003\x00\x00\x00\x00',
b'\x03896634760200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701004\x00\x00\x00\x00',
+ b'\x03896634760300\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701004\x00\x00\x00\x00',
b'\x03896634768000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4703001\x00\x00\x00\x00',
b'\x03896634768000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4703002\x00\x00\x00\x00',
b'\x03896634768100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4703002\x00\x00\x00\x00',
b'\x03896634785000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4705001\x00\x00\x00\x00',
+ b'\x03896634786000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4705001\x00\x00\x00\x00',
b'\x03896634786000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4710001\x00\x00\x00\x00',
b'\x03896634789000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4703002\x00\x00\x00\x00',
b'\x038966347A3000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4707001\x00\x00\x00\x00',
+ b'\x038966347B6000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4710001\x00\x00\x00\x00',
b'\x038966347B7000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4710001\x00\x00\x00\x00',
],
(Ecu.eps, 0x7a1, None): [
@@ -594,24 +781,26 @@ FW_VERSIONS = {
],
(Ecu.esp, 0x7b0, None): [
b'F152647290\x00\x00\x00\x00\x00\x00',
+ b'F152647300\x00\x00\x00\x00\x00\x00',
b'F152647310\x00\x00\x00\x00\x00\x00',
b'F152647414\x00\x00\x00\x00\x00\x00',
b'F152647415\x00\x00\x00\x00\x00\x00',
b'F152647416\x00\x00\x00\x00\x00\x00',
b'F152647417\x00\x00\x00\x00\x00\x00',
+ b'F152647470\x00\x00\x00\x00\x00\x00',
b'F152647490\x00\x00\x00\x00\x00\x00',
b'F152647684\x00\x00\x00\x00\x00\x00',
b'F152647862\x00\x00\x00\x00\x00\x00',
b'F152647863\x00\x00\x00\x00\x00\x00',
b'F152647864\x00\x00\x00\x00\x00\x00',
b'F152647865\x00\x00\x00\x00\x00\x00',
- b'F152647470\x00\x00\x00\x00\x00\x00',
],
(Ecu.dsu, 0x791, None): [
b'881514702300\x00\x00\x00\x00',
b'881514703100\x00\x00\x00\x00',
b'881514704100\x00\x00\x00\x00',
b'881514706000\x00\x00\x00\x00',
+ b'881514706100\x00\x00\x00\x00',
],
(Ecu.fwdRadar, 0x750, 0xf): [
b'8821F4702000\x00\x00\x00\x00',
@@ -632,20 +821,26 @@ FW_VERSIONS = {
(Ecu.engine, 0x7e0, None): [
b'\x02342Q1000\x00\x00\x00\x00\x00\x00\x00\x0054212000\x00\x00\x00\x00\x00\x00\x00\x00',
b'\x02342Q1100\x00\x00\x00\x00\x00\x00\x00\x0054212000\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'\x02342Q1200\x00\x00\x00\x00\x00\x00\x00\x0054212000\x00\x00\x00\x00\x00\x00\x00\x00',
b'\x02342Q1300\x00\x00\x00\x00\x00\x00\x00\x0054212000\x00\x00\x00\x00\x00\x00\x00\x00',
b'\x02342Q2000\x00\x00\x00\x00\x00\x00\x00\x0054213000\x00\x00\x00\x00\x00\x00\x00\x00',
b'\x02342Q2100\x00\x00\x00\x00\x00\x00\x00\x0054213000\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'\x02342Q2200\x00\x00\x00\x00\x00\x00\x00\x0054213000\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'\x02342Q4000\x00\x00\x00\x00\x00\x00\x00\x0054215000\x00\x00\x00\x00\x00\x00\x00\x00',
],
(Ecu.eps, 0x7a1, None): [
b'8965B42082\x00\x00\x00\x00\x00\x00',
b'8965B42083\x00\x00\x00\x00\x00\x00',
+ b'8965B42063\x00\x00\x00\x00\x00\x00',
],
(Ecu.esp, 0x7b0, None): [
b'F15260R102\x00\x00\x00\x00\x00\x00',
b'F15260R103\x00\x00\x00\x00\x00\x00',
b'F152642493\x00\x00\x00\x00\x00\x00',
+ b'F152642492\x00\x00\x00\x00\x00\x00',
],
(Ecu.dsu, 0x791, None): [
+ b'881514201200\x00\x00\x00\x00',
b'881514201300\x00\x00\x00\x00',
b'881514201400\x00\x00\x00\x00',
],
@@ -679,6 +874,7 @@ FW_VERSIONS = {
],
(Ecu.dsu, 0x791, None): [
b'881514202200\x00\x00\x00\x00',
+ b'881514202300\x00\x00\x00\x00',
b'881514202400\x00\x00\x00\x00',
],
(Ecu.fwdRadar, 0x750, 0xf): [
@@ -696,17 +892,23 @@ FW_VERSIONS = {
},
CAR.RAV4_TSS2: {
(Ecu.engine, 0x700, None): [
+ b'\x01896630R58000\x00\x00\x00\x00',
b'\x018966342E2000\x00\x00\x00\x00',
b'\x018966342M8000\x00\x00\x00\x00',
b'\x018966342T1000\x00\x00\x00\x00',
b'\x018966342T6000\x00\x00\x00\x00',
+ b'\x018966342T9000\x00\x00\x00\x00',
+ b'\x018966342U4000\x00\x00\x00\x00',
b'\x018966342V3100\x00\x00\x00\x00',
+ b'\x018966342V3200\x00\x00\x00\x00',
b'\x018966342X5000\x00\x00\x00\x00',
b'\x01896634A05000\x00\x00\x00\x00',
b'\x01896634A19000\x00\x00\x00\x00',
+ b'\x01896634A19100\x00\x00\x00\x00',
+ b'\x01896634A20000\x00\x00\x00\x00',
b'\x01896634A22000\x00\x00\x00\x00',
- b'\x018966342U4000\x00\x00\x00\x00',
b'\x01F152642551\x00\x00\x00\x00\x00\x00',
+ b'\x028966342T0000\x00\x00\x00\x00897CF1201001\x00\x00\x00\x00',
b'\x028966342Y8000\x00\x00\x00\x00897CF1201001\x00\x00\x00\x00',
b'\x02896634A18000\x00\x00\x00\x00897CF1201001\x00\x00\x00\x00',
],
@@ -714,13 +916,17 @@ FW_VERSIONS = {
b'F152642520\x00\x00\x00\x00\x00\x00',
b'\x01F15260R210\x00\x00\x00\x00\x00\x00',
b'\x01F15260R220\x00\x00\x00\x00\x00\x00',
+ b'\x01F15260R300\x00\x00\x00\x00\x00\x00',
b'\x01F152642551\x00\x00\x00\x00\x00\x00',
b'\x01F152642561\x00\x00\x00\x00\x00\x00',
+ b'\x01F152642700\x00\x00\x00\x00\x00\x00',
b'\x01F152642710\x00\x00\x00\x00\x00\x00',
+ b'\x01F152642750\x00\x00\x00\x00\x00\x00',
],
(Ecu.eps, 0x7a1, None): [
b'8965B42170\x00\x00\x00\x00\x00\x00',
b'8965B42171\x00\x00\x00\x00\x00\x00',
+ b'8965B42181\x00\x00\x00\x00\x00\x00',
b'\x028965B0R01200\x00\x00\x00\x008965B0R02200\x00\x00\x00\x00',
],
(Ecu.fwdRadar, 0x750, 0xf): [
@@ -734,13 +940,16 @@ FW_VERSIONS = {
b'\x028646F4203300\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00',
b'\x028646F4203400\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
b'\x028646F4203500\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
+ b'\x028646F4203700\x00\x00\x00\x008646G2601400\x00\x00\x00\x00',
],
},
CAR.RAV4H_TSS2: {
(Ecu.engine, 0x700, None): [
b'\x018966342M5000\x00\x00\x00\x00',
b'\x018966342X6000\x00\x00\x00\x00',
+ b'\x018966342W8000\x00\x00\x00\x00',
b'\x028966342W4001\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00',
+ b'\x02896634A14001\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00',
b'\x02896634A23001\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00',
],
(Ecu.esp, 0x7b0, None): [
@@ -749,22 +958,27 @@ FW_VERSIONS = {
b'F152642531\x00\x00\x00\x00\x00\x00',
b'F152642532\x00\x00\x00\x00\x00\x00',
b'F152642521\x00\x00\x00\x00\x00\x00',
+ b'F152642541\x00\x00\x00\x00\x00\x00',
],
(Ecu.eps, 0x7a1, None): [
b'8965B42170\x00\x00\x00\x00\x00\x00',
b'8965B42171\x00\x00\x00\x00\x00\x00',
b'8965B42181\x00\x00\x00\x00\x00\x00',
b'\x028965B0R01200\x00\x00\x00\x008965B0R02200\x00\x00\x00\x00',
+ b'\x028965B0R01300\x00\x00\x00\x008965B0R02300\x00\x00\x00\x00',
],
(Ecu.fwdRadar, 0x750, 0xf): [
+ b'\x018821F3301100\x00\x00\x00\x00',
b'\x018821F3301200\x00\x00\x00\x00',
b'\x018821F3301300\x00\x00\x00\x00',
b'\x018821F3301400\x00\x00\x00\x00',
],
(Ecu.fwdCamera, 0x750, 0x6d): [
+ b'\x028646F4203200\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00',
b'\x028646F4203300\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00',
b'\x028646F4203400\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
b'\x028646F4203500\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
+ b'\x028646F4203700\x00\x00\x00\x008646G2601400\x00\x00\x00\x00',
],
},
CAR.LEXUS_ES_TSS2: {
@@ -786,17 +1000,33 @@ FW_VERSIONS = {
CAR.SIENNA: {
(Ecu.engine, 0x700, None): [
b'\x01896630832100\x00\x00\x00\x00',
+ b'\x01896630838000\x00\x00\x00\x00',
+ b'\x01896630838100\x00\x00\x00\x00',
b'\x01896630842000\x00\x00\x00\x00',
+ b'\x01896630851000\x00\x00\x00\x00',
b'\x01896630851100\x00\x00\x00\x00',
- b'\x01896630860000\x00\x00\x00\x00',
+ b'\x01896630852100\x00\x00\x00\x00',
b'\x01896630859000\x00\x00\x00\x00',
+ b'\x01896630860000\x00\x00\x00\x00',
+ ],
+ (Ecu.eps, 0x7a1, None): [
+ b'8965B45070\x00\x00\x00\x00\x00\x00',
+ b'8965B45082\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.esp, 0x7b0, None): [
+ b'F152608130\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.dsu, 0x791, None): [
+ b'881510801100\x00\x00\x00\x00',
],
- (Ecu.eps, 0x7a1, None): [b'8965B45070\x00\x00\x00\x00\x00\x00'],
(Ecu.fwdRadar, 0x750, 0xf): [
b'8821F4702100\x00\x00\x00\x00',
+ b'8821F4702200\x00\x00\x00\x00',
b'8821F4702300\x00\x00\x00\x00',
],
- (Ecu.fwdCamera, 0x750, 0x6d): [b'8646F0801100\x00\x00\x00\x00'],
+ (Ecu.fwdCamera, 0x750, 0x6d): [
+ b'8646F0801100\x00\x00\x00\x00',
+ ],
},
CAR.LEXUS_ESH_TSS2: {
(Ecu.engine, 0x700, None): [
@@ -820,27 +1050,88 @@ FW_VERSIONS = {
b'\x028646F3304100\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
],
},
+ CAR.LEXUS_NXH: {
+ (Ecu.engine, 0x7e0, None): [
+ b'\x0237882000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'\x0237841000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.esp, 0x7b0, None): [
+ b'F152678160\x00\x00\x00\x00\x00\x00',
+ b'F152678170\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.dsu, 0x791, None): [
+ b'881517804300\x00\x00\x00\x00',
+ b'881517804100\x00\x00\x00\x00',
+ ],
+ (Ecu.eps, 0x7a1, None): [
+ b'8965B78100\x00\x00\x00\x00\x00\x00',
+ b'8965B78060\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdRadar, 0x750, 0xf): [
+ b'8821F4702300\x00\x00\x00\x00',
+ b'8821F4702100\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdCamera, 0x750, 0x6d): [
+ b'8646F7801300\x00\x00\x00\x00',
+ b'8646F7801100\x00\x00\x00\x00',
+ ],
+ },
CAR.LEXUS_RX: {
- (Ecu.engine, 0x700, None): [b'\x01896630E41200\x00\x00\x00\x00'],
- (Ecu.esp, 0x7b0, None): [b'F152648473\x00\x00\x00\x00\x00\x00'],
- (Ecu.dsu, 0x791, None): [b'881514810500\x00\x00\x00\x00'],
- (Ecu.eps, 0x7a1, None): [b'8965B0E012\x00\x00\x00\x00\x00\x00'],
- (Ecu.fwdRadar, 0x750, 0xf): [b'8821F4701100\x00\x00\x00\x00'],
- (Ecu.fwdCamera, 0x750, 0x6d): [b'8646F4802001\x00\x00\x00\x00'],
+ (Ecu.engine, 0x700, None): [
+ b'\x01896630E37200\x00\x00\x00\x00',
+ b'\x01896630E41000\x00\x00\x00\x00',
+ b'\x01896630E41200\x00\x00\x00\x00',
+ b'\x01896630E37300\x00\x00\x00\x00',
+ b'\x018966348R8500\x00\x00\x00\x00',
+ ],
+ (Ecu.esp, 0x7b0, None): [
+ b'F152648472\x00\x00\x00\x00\x00\x00',
+ b'F152648473\x00\x00\x00\x00\x00\x00',
+ b'F152648492\x00\x00\x00\x00\x00\x00',
+ b'F152648493\x00\x00\x00\x00\x00\x00',
+ b'F152648474\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.dsu, 0x791, None): [
+ b'881514810300\x00\x00\x00\x00',
+ b'881514810500\x00\x00\x00\x00',
+ b'881514810700\x00\x00\x00\x00',
+ ],
+ (Ecu.eps, 0x7a1, None): [
+ b'8965B0E011\x00\x00\x00\x00\x00\x00',
+ b'8965B0E012\x00\x00\x00\x00\x00\x00',
+ b'8965B48102\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdRadar, 0x750, 0xf): [
+ b'8821F4701000\x00\x00\x00\x00',
+ b'8821F4701100\x00\x00\x00\x00',
+ b'8821F4701300\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdCamera, 0x750, 0x6d): [
+ b'8646F4801100\x00\x00\x00\x00',
+ b'8646F4801200\x00\x00\x00\x00',
+ b'8646F4802001\x00\x00\x00\x00',
+ b'8646F4802100\x00\x00\x00\x00',
+ b'8646F4809000\x00\x00\x00\x00',
+ ],
},
CAR.LEXUS_RXH: {
(Ecu.engine, 0x7e0, None): [
+ b'\x02348N0000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00',
b'\x02348Q4000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00',
b'\x02348T1100\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'\x02348V6000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00',
b'\x02348Z3000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00',
],
(Ecu.esp, 0x7b0, None): [
+ b'F152648361\x00\x00\x00\x00\x00\x00',
b'F152648501\x00\x00\x00\x00\x00\x00',
+ b'F152648502\x00\x00\x00\x00\x00\x00',
+ b'F152648504\x00\x00\x00\x00\x00\x00',
b'F152648A30\x00\x00\x00\x00\x00\x00',
- b'F152648361\x00\x00\x00\x00\x00\x00',
],
(Ecu.dsu, 0x791, None): [
b'881514811300\x00\x00\x00\x00',
+ b'881514811500\x00\x00\x00\x00',
b'881514811700\x00\x00\x00\x00',
],
(Ecu.eps, 0x7a1, None): [
@@ -850,14 +1141,55 @@ FW_VERSIONS = {
],
(Ecu.fwdRadar, 0x750, 0xf): [
b'8821F4701000\x00\x00\x00\x00',
+ b'8821F4701100\x00\x00\x00\x00',
+ b'8821F4701200\x00\x00\x00\x00',
b'8821F4701300\x00\x00\x00\x00',
],
(Ecu.fwdCamera, 0x750, 0x6d): [
b'8646F4801200\x00\x00\x00\x00',
+ b'8646F4802100\x00\x00\x00\x00',
b'8646F4802200\x00\x00\x00\x00',
b'8646F4809000\x00\x00\x00\x00',
],
},
+ CAR.LEXUS_RX_TSS2: {
+ (Ecu.engine, 0x700, None): [
+ b'\x01896630EB0000\x00\x00\x00\x00',
+ b'\x01896630EA9000\x00\x00\x00\x00',
+ ],
+ (Ecu.esp, 0x7b0, None): [
+ b'\x01F15260E031\x00\x00\x00\x00\x00\x00',
+ b'\x01F15260E041\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.eps, 0x7a1, None): [
+ b'8965B48271\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdRadar, 0x750, 0xf): [
+ b'\x018821F3301100\x00\x00\x00\x00',
+ b'\x018821F3301300\x00\x00\x00\x00',
+ b'\x018821F3301400\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdCamera, 0x750, 0x6d): [
+ b'\x028646F4810100\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
+ ],
+ },
+ CAR.LEXUS_RXH_TSS2: {
+ (Ecu.engine, 0x7e0, None): [
+ b'\x02348X8000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.esp, 0x7b0, None): [
+ b'F152648831\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.eps, 0x7a1, None): [
+ b'8965B48271\x00\x00\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdRadar, 0x750, 0xf): [
+ b'\x018821F3301400\x00\x00\x00\x00',
+ ],
+ (Ecu.fwdCamera, 0x750, 0x6d): [
+ b'\x028646F4810100\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
+ ],
+ },
}
STEER_THRESHOLD = 100
@@ -870,6 +1202,7 @@ DBC = {
CAR.LEXUS_RX: dbc_dict('lexus_rx_350_2016_pt_generated', 'toyota_adas'),
CAR.LEXUS_RXH: dbc_dict('lexus_rx_hybrid_2017_pt_generated', 'toyota_adas'),
CAR.LEXUS_RX_TSS2: dbc_dict('toyota_nodsu_pt_generated', 'toyota_tss2_adas'),
+ CAR.LEXUS_RXH_TSS2: dbc_dict('toyota_nodsu_hybrid_pt_generated', 'toyota_tss2_adas'),
CAR.CHR: dbc_dict('toyota_nodsu_pt_generated', 'toyota_adas'),
CAR.CHRH: dbc_dict('toyota_nodsu_hybrid_pt_generated', 'toyota_adas'),
CAR.CAMRY: dbc_dict('toyota_nodsu_pt_generated', 'toyota_adas'),
@@ -891,6 +1224,6 @@ DBC = {
CAR.LEXUS_NXH: dbc_dict('lexus_nx300h_2018_pt_generated', 'toyota_adas'),
}
-NO_DSU_CAR = [CAR.CHR, CAR.CHRH, CAR.CAMRY, CAR.CAMRYH, CAR.RAV4_TSS2, CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2, CAR.LEXUS_ES_TSS2, CAR.LEXUS_ESH_TSS2, CAR.RAV4H_TSS2, CAR.LEXUS_RX_TSS2, CAR.HIGHLANDER_TSS2, CAR.HIGHLANDERH_TSS2]
-TSS2_CAR = [CAR.RAV4_TSS2, CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2, CAR.LEXUS_ES_TSS2, CAR.LEXUS_ESH_TSS2, CAR.RAV4H_TSS2, CAR.LEXUS_RX_TSS2, CAR.HIGHLANDER_TSS2, CAR.HIGHLANDERH_TSS2]
-NO_STOP_TIMER_CAR = [CAR.RAV4H, CAR.HIGHLANDERH, CAR.HIGHLANDER, CAR.RAV4_TSS2, CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2, CAR.LEXUS_ES_TSS2, CAR.LEXUS_ESH_TSS2, CAR.SIENNA, CAR.RAV4H_TSS2, CAR.LEXUS_RX_TSS2, CAR.HIGHLANDER_TSS2, CAR.HIGHLANDERH_TSS2] # no resume button press required
+NO_DSU_CAR = set([CAR.CHR, CAR.CHRH, CAR.CAMRY, CAR.CAMRYH, CAR.RAV4_TSS2, CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2, CAR.LEXUS_ES_TSS2, CAR.LEXUS_ESH_TSS2, CAR.RAV4H_TSS2, CAR.LEXUS_RX_TSS2, CAR.LEXUS_RXH_TSS2, CAR.HIGHLANDER_TSS2, CAR.HIGHLANDERH_TSS2])
+TSS2_CAR = set([CAR.RAV4_TSS2, CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2, CAR.LEXUS_ES_TSS2, CAR.LEXUS_ESH_TSS2, CAR.RAV4H_TSS2, CAR.LEXUS_RX_TSS2, CAR.LEXUS_RXH_TSS2, CAR.HIGHLANDER_TSS2, CAR.HIGHLANDERH_TSS2])
+NO_STOP_TIMER_CAR = set([CAR.RAV4H, CAR.HIGHLANDERH, CAR.HIGHLANDER, CAR.RAV4_TSS2, CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2, CAR.LEXUS_ES_TSS2, CAR.LEXUS_ESH_TSS2, CAR.SIENNA, CAR.RAV4H_TSS2, CAR.LEXUS_RX_TSS2, CAR.LEXUS_RXH_TSS2, CAR.HIGHLANDER_TSS2, CAR.HIGHLANDERH_TSS2]) # no resume button press required
diff --git a/selfdrive/car/volkswagen/__init__.py b/selfdrive/car/volkswagen/__init__.py
index 8b13789179..e69de29bb2 100644
--- a/selfdrive/car/volkswagen/__init__.py
+++ b/selfdrive/car/volkswagen/__init__.py
@@ -1 +0,0 @@
-
diff --git a/selfdrive/car/volkswagen/carcontroller.py b/selfdrive/car/volkswagen/carcontroller.py
index 6c90d69e78..5bb5dcc109 100644
--- a/selfdrive/car/volkswagen/carcontroller.py
+++ b/selfdrive/car/volkswagen/carcontroller.py
@@ -4,8 +4,6 @@ from selfdrive.car.volkswagen import volkswagencan
from selfdrive.car.volkswagen.values import DBC, CANBUS, MQB_LDW_MESSAGES, BUTTON_STATES, CarControllerParams
from opendbc.can.packer import CANPacker
-VisualAlert = car.CarControl.HUDControl.VisualAlert
-
class CarController():
def __init__(self, dbc_name, CP, VM):
@@ -67,7 +65,7 @@ class CarController():
self.hcaEnabledFrameCount = 0
else:
self.hcaEnabledFrameCount += 1
- if self.hcaEnabledFrameCount >= 118 * (100 / P.HCA_STEP): # 118s
+ if self.hcaEnabledFrameCount >= 118 * (100 / P.HCA_STEP): # 118s
# The Kansas I-70 Crosswind Problem: if we truly do need to steer
# in one direction for > 360 seconds, we have to disable HCA for a
# frame while actively steering. Testing shows we can just set the
@@ -114,7 +112,7 @@ class CarController():
if frame % P.LDW_STEP == 0:
hcaEnabled = True if enabled and not CS.out.standstill else False
- if visual_alert == VisualAlert.steerRequired:
+ if visual_alert == car.CarControl.HUDControl.VisualAlert.steerRequired:
hud_alert = MQB_LDW_MESSAGES["laneAssistTakeOverSilent"]
else:
hud_alert = MQB_LDW_MESSAGES["none"]
diff --git a/selfdrive/car/volkswagen/carstate.py b/selfdrive/car/volkswagen/carstate.py
index 91b24dc4ff..a994130929 100644
--- a/selfdrive/car/volkswagen/carstate.py
+++ b/selfdrive/car/volkswagen/carstate.py
@@ -28,16 +28,16 @@ class CarState(CarStateBase):
# Update steering angle, rate, yaw rate, and driver input torque. VW send
# the sign/direction in a separate signal so they must be recombined.
- ret.steeringAngle = pt_cp.vl["LWI_01"]['LWI_Lenkradwinkel'] * (1,-1)[int(pt_cp.vl["LWI_01"]['LWI_VZ_Lenkradwinkel'])]
- ret.steeringRate = pt_cp.vl["LWI_01"]['LWI_Lenkradw_Geschw'] * (1,-1)[int(pt_cp.vl["LWI_01"]['LWI_VZ_Lenkradwinkel'])]
- ret.steeringTorque = pt_cp.vl["EPS_01"]['Driver_Strain'] * (1,-1)[int(pt_cp.vl["EPS_01"]['Driver_Strain_VZ'])]
+ ret.steeringAngle = pt_cp.vl["LWI_01"]['LWI_Lenkradwinkel'] * (1, -1)[int(pt_cp.vl["LWI_01"]['LWI_VZ_Lenkradwinkel'])]
+ ret.steeringRate = pt_cp.vl["LWI_01"]['LWI_Lenkradw_Geschw'] * (1, -1)[int(pt_cp.vl["LWI_01"]['LWI_VZ_Lenkradwinkel'])]
+ ret.steeringTorque = pt_cp.vl["EPS_01"]['Driver_Strain'] * (1, -1)[int(pt_cp.vl["EPS_01"]['Driver_Strain_VZ'])]
ret.steeringPressed = abs(ret.steeringTorque) > CarControllerParams.STEER_DRIVER_ALLOWANCE
- ret.yawRate = pt_cp.vl["ESP_02"]['ESP_Gierrate'] * (1,-1)[int(pt_cp.vl["ESP_02"]['ESP_VZ_Gierrate'])] * CV.DEG_TO_RAD
+ ret.yawRate = pt_cp.vl["ESP_02"]['ESP_Gierrate'] * (1, -1)[int(pt_cp.vl["ESP_02"]['ESP_VZ_Gierrate'])] * CV.DEG_TO_RAD
# Update gas, brakes, and gearshift.
ret.gas = pt_cp.vl["Motor_20"]['MO_Fahrpedalrohwert_01'] / 100.0
ret.gasPressed = ret.gas > 0
- ret.brake = pt_cp.vl["ESP_05"]['ESP_Bremsdruck'] / 250.0 # FIXME: this is pressure in Bar, not sure what OP expects
+ ret.brake = pt_cp.vl["ESP_05"]['ESP_Bremsdruck'] / 250.0 # FIXME: this is pressure in Bar, not sure what OP expects
ret.brakePressed = bool(pt_cp.vl["ESP_05"]['ESP_Fahrer_bremst'])
ret.brakeLights = bool(pt_cp.vl["ESP_05"]['ESP_Status_Bremsdruck'])
@@ -53,7 +53,7 @@ class CarState(CarStateBase):
pt_cp.vl["Gateway_72"]['ZV_HD_offen']])
# Update seatbelt fastened status.
- ret.seatbeltUnlatched = False if pt_cp.vl["Airbag_02"]["AB_Gurtschloss_FA"] == 3 else True
+ ret.seatbeltUnlatched = pt_cp.vl["Airbag_02"]["AB_Gurtschloss_FA"] != 3
# Update driver preference for metric. VW stores many different unit
# preferences, including separate units for for distance vs. speed.
@@ -107,7 +107,7 @@ class CarState(CarStateBase):
self.steeringFault = not pt_cp.vl["EPS_01"]["HCA_Ready"]
# Additional safety checks performed in CarInterface.
- self.parkingBrakeSet = bool(pt_cp.vl["Kombi_01"]['KBI_Handbremse']) # FIXME: need to include an EPB check as well
+ self.parkingBrakeSet = bool(pt_cp.vl["Kombi_01"]['KBI_Handbremse']) # FIXME: need to include an EPB check as well
ret.espDisabled = pt_cp.vl["ESP_21"]['ESP_Tastung_passiv'] != 0
return ret
@@ -159,7 +159,7 @@ class CarState(CarStateBase):
("GRA_Tip_Hoch", "GRA_ACC_01", 0), # ACC button, increase or accel
("GRA_Tip_Runter", "GRA_ACC_01", 0), # ACC button, decrease or decel
("GRA_Tip_Wiederaufnahme", "GRA_ACC_01", 0), # ACC button, resume
- ("GRA_Verstellung_Zeitluecke", "GRA_ACC_01", 0), # ACC button, time gap adj
+ ("GRA_Verstellung_Zeitluecke", "GRA_ACC_01", 0), # ACC button, time gap adj
("GRA_Typ_Hauptschalter", "GRA_ACC_01", 0), # ACC main button type
("GRA_Tip_Stufe_2", "GRA_ACC_01", 0), # unknown related to stalk type
("GRA_ButtonTypeInfo", "GRA_ACC_01", 0), # unknown related to stalk type
diff --git a/selfdrive/car/volkswagen/interface.py b/selfdrive/car/volkswagen/interface.py
index 8e2797de9c..c041c6c44c 100644
--- a/selfdrive/car/volkswagen/interface.py
+++ b/selfdrive/car/volkswagen/interface.py
@@ -1,7 +1,5 @@
from cereal import car
-from selfdrive.config import Conversions as CV
from selfdrive.car.volkswagen.values import CAR, BUTTON_STATES
-from common.params import put_nonblocking
from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint
from selfdrive.car.interfaces import CarInterfaceBase
@@ -20,7 +18,7 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 4.0
@staticmethod
- def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]):
+ def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay)
# VW port is a community feature, since we don't own one to test
@@ -33,35 +31,23 @@ class CarInterface(CarInterfaceBase):
ret.safetyModel = car.CarParams.SafetyModel.volkswagen
# Additional common MQB parameters that may be overridden per-vehicle
- ret.steerRateCost = 0.5
- ret.steerActuatorDelay = 0.05 # Hopefully all MQB racks are similar here
+ ret.steerRateCost = 1.0
+ ret.steerActuatorDelay = 0.05 # Hopefully all MQB racks are similar here
ret.steerLimitTimer = 0.4
- # As a starting point for speed-adjusted lateral tuning, use the example
- # map speed breakpoints from a VW Tiguan (SSP 399 page 9). It's unclear
- # whether the driver assist map breakpoints have any direct bearing on
- # HCA assist torque, but if they're good breakpoints for the driver,
- # they're probably good breakpoints for HCA as well. OP won't be driving
- # 250kph/155mph but it provides interpolation scaling above 100kmh/62mph.
- ret.lateralTuning.pid.kpBP = [0., 15 * CV.KPH_TO_MS, 50 * CV.KPH_TO_MS]
- ret.lateralTuning.pid.kiBP = [0., 15 * CV.KPH_TO_MS, 50 * CV.KPH_TO_MS]
-
- # FIXME: Per-vehicle parameters need to be reintegrated.
- # For the time being, per-vehicle stuff is being archived since we
- # can't auto-detect very well yet. Now that tuning is figured out,
- # averaged params should work reasonably on a range of cars. Owners
- # can tweak here, as needed, until we have car type auto-detection.
-
- ret.mass = 1700 + STD_CARGO_KG
- ret.wheelbase = 2.75
+ ret.lateralTuning.pid.kpBP = [0.]
+ ret.lateralTuning.pid.kiBP = [0.]
+
+ ret.mass = 1500 + STD_CARGO_KG
+ ret.wheelbase = 2.64
ret.centerToFront = ret.wheelbase * 0.45
ret.steerRatio = 15.6
ret.lateralTuning.pid.kf = 0.00006
- ret.lateralTuning.pid.kpV = [0.15, 0.25, 0.60]
- ret.lateralTuning.pid.kiV = [0.05, 0.05, 0.05]
- tire_stiffness_factor = 0.6
+ ret.lateralTuning.pid.kpV = [0.6]
+ ret.lateralTuning.pid.kiV = [0.2]
+ tire_stiffness_factor = 1.0
- ret.enableCamera = True # Stock camera detection doesn't apply to VW
+ ret.enableCamera = True # Stock camera detection doesn't apply to VW
ret.transmissionType = car.CarParams.TransmissionType.automatic
# TODO: get actual value, for now starting with reasonable value for
@@ -77,7 +63,6 @@ class CarInterface(CarInterfaceBase):
# returns a car.CarState
def update(self, c, can_strings):
- canMonoTimes = []
buttonEvents = []
# Process the most recent CAN message traffic, and check for validity
@@ -90,10 +75,11 @@ class CarInterface(CarInterfaceBase):
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
ret.steeringRateLimited = self.CC.steer_rate_limited if self.CC is not None else False
- # Update the EON metric configuration to match the car at first startup,
+ # TODO: add a field for this to carState, car interface code shouldn't write params
+ # Update the device metric configuration to match the car at first startup,
# or if there's been a change.
- if self.CS.displayMetricUnits != self.displayMetricUnitsPrev:
- put_nonblocking("IsMetric", "1" if self.CS.displayMetricUnits else "0")
+ #if self.CS.displayMetricUnits != self.displayMetricUnitsPrev:
+ # put_nonblocking("IsMetric", "1" if self.CS.displayMetricUnits else "0")
# Check for and process state-change events (button press or release) from
# the turn stalk switch or ACC steering wheel/control stalk buttons.
@@ -114,7 +100,6 @@ class CarInterface(CarInterfaceBase):
ret.events = events.to_msg()
ret.buttonEvents = buttonEvents
- ret.canMonoTimes = canMonoTimes
# update previous car states
self.displayMetricUnitsPrev = self.CS.displayMetricUnits
diff --git a/selfdrive/car/volkswagen/values.py b/selfdrive/car/volkswagen/values.py
index 30c32b6080..d99d781026 100644
--- a/selfdrive/car/volkswagen/values.py
+++ b/selfdrive/car/volkswagen/values.py
@@ -1,3 +1,5 @@
+# flake8: noqa
+
from selfdrive.car import dbc_dict
class CarControllerParams:
@@ -44,7 +46,7 @@ MQB_LDW_MESSAGES = {
}
class CAR:
- GOLF = "Volkswagen Golf"
+ GOLF = "VOLKSWAGEN GOLF"
FINGERPRINTS = {
CAR.GOLF: [
diff --git a/selfdrive/car/volkswagen/volkswagencan.py b/selfdrive/car/volkswagen/volkswagencan.py
index 34f19003d8..3cd47a0957 100644
--- a/selfdrive/car/volkswagen/volkswagencan.py
+++ b/selfdrive/car/volkswagen/volkswagencan.py
@@ -25,7 +25,7 @@ def create_mqb_hud_control(packer, bus, hca_enabled, steering_pressed, hud_alert
rightlanehud = 2 if rightLaneVisible else 1
values = {
- "LDW_Unknown": 2, # FIXME: possible speed or attention relationship
+ "LDW_Unknown": 2, # FIXME: possible speed or attention relationship
"Kombi_Lamp_Orange": 1 if hca_enabled and steering_pressed else 0,
"Kombi_Lamp_Green": 1 if hca_enabled and not steering_pressed else 0,
"Left_Lane_Status": leftlanehud,
@@ -48,5 +48,4 @@ def create_mqb_acc_buttons_control(packer, bus, buttonStatesToSend, CS, idx):
"GRA_Tip_Stufe_2": CS.graTipStufe2,
"GRA_ButtonTypeInfo": CS.graButtonTypeInfo
}
-
return packer.make_can_msg("GRA_ACC_01", bus, values, idx)
diff --git a/selfdrive/clocksd/SConscript b/selfdrive/clocksd/SConscript
index 63c508c4fe..601e64bf16 100644
--- a/selfdrive/clocksd/SConscript
+++ b/selfdrive/clocksd/SConscript
@@ -1,2 +1,2 @@
-Import('env', 'common', 'messaging')
-env.Program('clocksd.cc', LIBS=['diag', 'time_genoff', common, messaging, 'capnp', 'zmq', 'kj'])
\ No newline at end of file
+Import('env', 'common', 'cereal', 'messaging')
+env.Program('clocksd.cc', LIBS=['diag', 'time_genoff', common, cereal, messaging, 'capnp', 'zmq', 'kj'])
\ No newline at end of file
diff --git a/selfdrive/clocksd/clocksd.cc b/selfdrive/clocksd/clocksd.cc
index d289387a8b..2e17058e0e 100644
--- a/selfdrive/clocksd/clocksd.cc
+++ b/selfdrive/clocksd/clocksd.cc
@@ -4,10 +4,8 @@
#include
#include
#include
-#include
#include "messaging.hpp"
#include "common/timing.h"
-#include "cereal/gen/cpp/log.capnp.h"
namespace {
int64_t arm_cntpct() {
@@ -21,10 +19,7 @@ int main() {
setpriority(PRIO_PROCESS, 0, -13);
int err = 0;
- Context *context = Context::create();
-
- PubSocket* clock_publisher = PubSocket::create(context, "clocks");
- assert(clock_publisher != NULL);
+ PubMaster pm({"clocks"});
int timerfd = timerfd_create(CLOCK_BOOTTIME, 0);
assert(timerfd >= 0);
@@ -60,13 +55,9 @@ int main() {
clocks.setWallTimeNanos(wall_time);
clocks.setModemUptimeMillis(modem_uptime_v);
- auto words = capnp::messageToFlatArray(msg);
- auto bytes = words.asBytes();
- clock_publisher->send((char*)bytes.begin(), bytes.size());
+ pm.send("clocks", msg);
}
close(timerfd);
- delete clock_publisher;
- delete context;
return 0;
}
\ No newline at end of file
diff --git a/selfdrive/common/SConscript b/selfdrive/common/SConscript
index 18f9fdf4a8..0ba5b1abcc 100644
--- a/selfdrive/common/SConscript
+++ b/selfdrive/common/SConscript
@@ -1,11 +1,11 @@
-Import('env', 'arch', 'SHARED')
+Import('env', 'arch', 'SHARED', 'QCOM_REPLAY')
if SHARED:
fxn = env.SharedLibrary
else:
fxn = env.Library
-_common = fxn('common', ['params.cc', 'swaglog.cc', 'util.c', 'cqueue.c'], LIBS="json11")
+_common = fxn('common', ['params.cc', 'swaglog.cc', 'util.c', 'cqueue.c', 'gpio.cc'], LIBS="json11")
_visionipc = fxn('visionipc', ['visionipc.c', 'ipc.c'])
files = [
@@ -21,8 +21,11 @@ if arch == "aarch64":
files += [
'framebuffer.cc',
'touch.c',
- 'visionbuf_ion.c',
]
+ if QCOM_REPLAY:
+ files += ['visionbuf_cl.c']
+ else:
+ files += ['visionbuf_ion.c']
_gpu_libs = ['gui', 'adreno_utils']
elif arch == "larch64":
defines = {"CLU_NO_CACHE": None}
@@ -39,4 +42,3 @@ else:
_gpucommon = fxn('gpucommon', files, CPPDEFINES=defines, LIBS=_gpu_libs)
Export('_common', '_visionipc', '_gpucommon', '_gpu_libs')
-
diff --git a/selfdrive/common/buffering.c b/selfdrive/common/buffering.c
index 9cbb1b86e0..bba2e82ab9 100644
--- a/selfdrive/common/buffering.c
+++ b/selfdrive/common/buffering.c
@@ -70,7 +70,7 @@ void tbuffer_dispatch(TBuffer *tb, int idx) {
efd_write(tb->efd);
pthread_cond_signal(&tb->cv);
- pthread_mutex_unlock(&tb->lock);
+ pthread_mutex_unlock(&tb->lock);
}
int tbuffer_acquire(TBuffer *tb) {
@@ -344,7 +344,7 @@ void pool_push(Pool *s, int idx) {
for (int i=0; iqueues[i];
if (!c->inited) continue;
-
+
pthread_mutex_lock(&c->lock);
if (((c->head+1) % c->num) == c->tail) {
// queue is full. skip for now
diff --git a/selfdrive/common/clutil.c b/selfdrive/common/clutil.c
index 22c9b45de1..00d63cdcac 100644
--- a/selfdrive/common/clutil.c
+++ b/selfdrive/common/clutil.c
@@ -36,6 +36,44 @@ void clu_init(void) {
#endif
}
+cl_device_id cl_get_device_id(cl_device_type device_type) {
+ bool opencl_platform_found = false;
+ cl_device_id device_id = NULL;
+
+ cl_uint num_platforms = 0;
+ int err = clGetPlatformIDs(0, NULL, &num_platforms);
+ assert(err == 0);
+ cl_platform_id* platform_ids = malloc(sizeof(cl_platform_id) * num_platforms);
+ err = clGetPlatformIDs(num_platforms, platform_ids, NULL);
+ assert(err == 0);
+
+ char cBuffer[1024];
+ for (size_t i = 0; i < num_platforms; i++) {
+ err = clGetPlatformInfo(platform_ids[i], CL_PLATFORM_NAME, sizeof(cBuffer), &cBuffer, NULL);
+ assert(err == 0);
+ printf("platform[%zu] CL_PLATFORM_NAME: %s\n", i, cBuffer);
+
+ cl_uint num_devices;
+ err = clGetDeviceIDs(platform_ids[i], device_type, 0, NULL, &num_devices);
+ if (err != 0 || !num_devices) {
+ continue;
+ }
+ // Get first device
+ err = clGetDeviceIDs(platform_ids[i], device_type, 1, &device_id, NULL);
+ assert(err == 0);
+ cl_print_info(platform_ids[i], device_id);
+ opencl_platform_found = true;
+ break;
+ }
+ free(platform_ids);
+
+ if (!opencl_platform_found) {
+ printf("No valid openCL platform found\n");
+ assert(opencl_platform_found);
+ }
+ return device_id;
+}
+
cl_program cl_create_program_from_file(cl_context ctx, const char* path) {
char* src_buf = read_file(path, NULL);
assert(src_buf);
@@ -175,6 +213,7 @@ cl_program cl_cached_program_from_hash(cl_context ctx, cl_device_id device_id, u
return prg;
}
+#ifndef CLU_NO_CACHE
static uint8_t* get_program_binary(cl_program prg, size_t *out_size) {
int err;
@@ -199,6 +238,7 @@ static uint8_t* get_program_binary(cl_program prg, size_t *out_size) {
*out_size = binary_size;
return binary_buf;
}
+#endif
cl_program cl_cached_program_from_string(cl_context ctx, cl_device_id device_id,
const char* src, const char* args,
@@ -265,13 +305,14 @@ cl_program cl_cached_program_from_file(cl_context ctx, cl_device_id device_id, c
return ret;
}
+#ifndef CLU_NO_CACHE
static void add_index(uint64_t index_hash, uint64_t src_hash) {
FILE *f = fopen("/tmp/clcache/index.cli", "a");
assert(f);
fprintf(f, "%016" PRIx64 " %016" PRIx64 "\n", index_hash, src_hash);
fclose(f);
}
-
+#endif
cl_program cl_program_from_index(cl_context ctx, cl_device_id device_id, uint64_t index_hash) {
int err;
diff --git a/selfdrive/common/clutil.h b/selfdrive/common/clutil.h
index b87961eacd..abbda8c806 100644
--- a/selfdrive/common/clutil.h
+++ b/selfdrive/common/clutil.h
@@ -17,6 +17,7 @@ extern "C" {
void clu_init(void);
+cl_device_id cl_get_device_id(cl_device_type device_type);
cl_program cl_create_program_from_file(cl_context ctx, const char* path);
void cl_print_info(cl_platform_id platform, cl_device_id device);
void cl_print_build_errors(cl_program program, cl_device_id device);
diff --git a/selfdrive/common/framebuffer.cc b/selfdrive/common/framebuffer.cc
index 7bea565d59..30604deb2e 100644
--- a/selfdrive/common/framebuffer.cc
+++ b/selfdrive/common/framebuffer.cc
@@ -12,8 +12,7 @@
#include
#include
-#define BACKLIGHT_CONTROL "/sys/class/leds/lcd-backlight/brightness"
-#define BACKLIGHT_LEVEL "205"
+#define BACKLIGHT_LEVEL 205
using namespace android;
@@ -32,6 +31,21 @@ struct FramebufferState {
EGLContext context;
};
+extern "C" void framebuffer_swap(FramebufferState *s) {
+ eglSwapBuffers(s->display, s->surface);
+ assert(glGetError() == GL_NO_ERROR);
+}
+
+extern "C" bool set_brightness(int brightness) {
+ FILE *f = fopen("/sys/class/leds/lcd-backlight/brightness", "wb");
+ if (f != NULL) {
+ fprintf(f, "%d", brightness);
+ fclose(f);
+ return true;
+ }
+ return false;
+}
+
extern "C" void framebuffer_set_power(FramebufferState *s, int mode) {
SurfaceComposerClient::setDisplayPowerMode(s->dtoken, mode);
}
@@ -88,6 +102,9 @@ extern "C" FramebufferState* framebuffer_init(
EGL_DEPTH_SIZE, 0,
EGL_STENCIL_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
+ // enable MSAA
+ EGL_SAMPLE_BUFFERS, 1,
+ EGL_SAMPLES, 4,
EGL_NONE,
};
@@ -98,7 +115,7 @@ extern "C" FramebufferState* framebuffer_init(
assert(success);
printf("egl version %d.%d\n", s->egl_major, s->egl_minor);
-
+
EGLint num_configs;
success = eglChooseConfig(s->display, attribs, &s->config, 1, &num_configs);
assert(success);
@@ -123,23 +140,10 @@ extern "C" FramebufferState* framebuffer_init(
printf("gl version %s\n", glGetString(GL_VERSION));
-
- // set brightness
- int brightness_fd = open(BACKLIGHT_CONTROL, O_RDWR);
- if (brightness_fd != -1){
- const char brightness_level[] = BACKLIGHT_LEVEL;
- write(brightness_fd, brightness_level, strlen(brightness_level));
- close(brightness_fd);
- }
+ set_brightness(BACKLIGHT_LEVEL);
if (out_w) *out_w = w;
if (out_h) *out_h = h;
return s;
}
-
-extern "C" void framebuffer_swap(FramebufferState *s) {
- eglSwapBuffers(s->display, s->surface);
- assert(glGetError() == GL_NO_ERROR);
-}
-
diff --git a/selfdrive/common/framebuffer.h b/selfdrive/common/framebuffer.h
index 45920b8e42..45053bbb14 100644
--- a/selfdrive/common/framebuffer.h
+++ b/selfdrive/common/framebuffer.h
@@ -1,5 +1,4 @@
-#ifndef FRAMEBUFFER_H
-#define FRAMEBUFFER_H
+#pragma once
#ifdef __cplusplus
extern "C" {
@@ -13,6 +12,7 @@ FramebufferState* framebuffer_init(
void framebuffer_set_power(FramebufferState *s, int mode);
void framebuffer_swap(FramebufferState *s);
+bool set_brightness(int brightness);
/* Display power modes */
enum {
@@ -40,9 +40,6 @@ enum {
HWC_POWER_MODE_DOZE_SUSPEND = 3,
};
-
#ifdef __cplusplus
}
#endif
-
-#endif
diff --git a/selfdrive/common/gpio.cc b/selfdrive/common/gpio.cc
new file mode 100644
index 0000000000..fd68bcd523
--- /dev/null
+++ b/selfdrive/common/gpio.cc
@@ -0,0 +1,75 @@
+#include "gpio.h"
+#include
+#include
+#include
+
+// We assume that all pins have already been exported on boot,
+// and that we have permission to write to them.
+
+int gpio_init(int pin_nr, bool output){
+ int ret = 0;
+ int fd = -1, tmp;
+
+ char pin_dir_path[50];
+ int pin_dir_path_len = snprintf(pin_dir_path, sizeof(pin_dir_path),
+ "/sys/class/gpio/gpio%d/direction", pin_nr);
+ if(pin_dir_path_len <= 0){
+ ret = -1;
+ goto cleanup;
+ }
+
+ fd = open(pin_dir_path, O_WRONLY);
+ if(fd == -1){
+ ret = -1;
+ goto cleanup;
+ }
+ if(output){
+ tmp = write(fd, "out", 3);
+ if(tmp != 3){
+ ret = -1;
+ goto cleanup;
+ }
+ } else {
+ tmp = write(fd, "in", 2);
+ if(tmp != 2){
+ ret = -1;
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if(fd >= 0){
+ close(fd);
+ }
+ return ret;
+}
+
+int gpio_set(int pin_nr, bool high){
+ int ret = 0;
+ int fd = -1, tmp;
+
+ char pin_val_path[50];
+ int pin_val_path_len = snprintf(pin_val_path, sizeof(pin_val_path),
+ "/sys/class/gpio/gpio%d/value", pin_nr);
+ if(pin_val_path_len <= 0){
+ ret = -1;
+ goto cleanup;
+ }
+
+ fd = open(pin_val_path, O_WRONLY);
+ if(fd == -1){
+ ret = -1;
+ goto cleanup;
+ }
+ tmp = write(fd, high ? "1" : "0", 1);
+ if(tmp != 1){
+ ret = -1;
+ goto cleanup;
+ }
+
+cleanup:
+ if(fd >= 0){
+ close(fd);
+ }
+ return ret;
+}
diff --git a/selfdrive/common/gpio.h b/selfdrive/common/gpio.h
new file mode 100644
index 0000000000..479b4f7e06
--- /dev/null
+++ b/selfdrive/common/gpio.h
@@ -0,0 +1,35 @@
+#ifndef GPIO_H
+#define GPIO_H
+
+#include
+
+// Pin definitions
+#ifdef QCOM2
+ #define GPIO_HUB_RST_N 30
+ #define GPIO_UBLOX_RST_N 32
+ #define GPIO_UBLOX_SAFEBOOT_N 33
+ #define GPIO_UBLOX_PWR_EN 34
+ #define GPIO_STM_RST_N 124
+ #define GPIO_STM_BOOT0 134
+#else
+ #define GPIO_HUB_RST_N 0
+ #define GPIO_UBLOX_RST_N 0
+ #define GPIO_UBLOX_SAFEBOOT_N 0
+ #define GPIO_UBLOX_PWR_EN 0
+ #define GPIO_STM_RST_N 0
+ #define GPIO_STM_BOOT0 0
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int gpio_init(int pin_nr, bool output);
+int gpio_set(int pin_nr, bool high);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
diff --git a/selfdrive/common/ipc.c b/selfdrive/common/ipc.c
index 41b0cc0eaa..a5993598d2 100644
--- a/selfdrive/common/ipc.c
+++ b/selfdrive/common/ipc.c
@@ -15,7 +15,11 @@
int ipc_connect(const char* socket_path) {
int err;
+#ifdef __APPLE__
+ int sock = socket(AF_UNIX, SOCK_STREAM, 0);
+#else
int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+#endif
if (sock < 0) return -1;
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
@@ -35,7 +39,11 @@ int ipc_bind(const char* socket_path) {
unlink(socket_path);
+#ifdef __APPLE__
+ int sock = socket(AF_UNIX, SOCK_STREAM, 0);
+#else
int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+#endif
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
};
@@ -52,8 +60,6 @@ int ipc_bind(const char* socket_path) {
int ipc_sendrecv_with_fds(bool send, int fd, void *buf, size_t buf_size, int* fds, int num_fds,
int *out_num_fds) {
- int err;
-
char control_buf[CMSG_SPACE(sizeof(int) * num_fds)];
memset(control_buf, 0, CMSG_SPACE(sizeof(int) * num_fds));
diff --git a/selfdrive/common/messaging.h b/selfdrive/common/messaging.h
deleted file mode 100644
index dd1198e826..0000000000
--- a/selfdrive/common/messaging.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// the c version of cereal/messaging.py
-
-#include
-
-// TODO: refactor to take in service instead of endpoint?
-void *sub_sock(void *ctx, const char *endpoint) {
- void* sock = zmq_socket(ctx, ZMQ_SUB);
- assert(sock);
- zmq_setsockopt(sock, ZMQ_SUBSCRIBE, "", 0);
- int reconnect_ivl = 500;
- zmq_setsockopt(sock, ZMQ_RECONNECT_IVL_MAX, &reconnect_ivl, sizeof(reconnect_ivl));
- zmq_connect(sock, endpoint);
- return sock;
-}
-
diff --git a/selfdrive/common/modeldata.h b/selfdrive/common/modeldata.h
index 555a75614c..77f4a1b7a1 100644
--- a/selfdrive/common/modeldata.h
+++ b/selfdrive/common/modeldata.h
@@ -1,40 +1,7 @@
-#ifndef MODELDATA_H
-#define MODELDATA_H
+#pragma once
#define MODEL_PATH_DISTANCE 192
#define POLYFIT_DEGREE 4
#define SPEED_PERCENTILES 10
#define DESIRE_PRED_SIZE 32
#define OTHER_META_SIZE 4
-
-typedef struct PathData {
- float points[MODEL_PATH_DISTANCE];
- float prob;
- float std;
- float stds[MODEL_PATH_DISTANCE];
- float poly[POLYFIT_DEGREE];
-} PathData;
-
-typedef struct LeadData {
- float dist;
- float prob;
- float std;
- float rel_y;
- float rel_y_std;
- float rel_v;
- float rel_v_std;
- float rel_a;
- float rel_a_std;
-} LeadData;
-
-typedef struct ModelData {
- PathData path;
- PathData left_lane;
- PathData right_lane;
- LeadData lead;
- LeadData lead_future;
- float meta[OTHER_META_SIZE + DESIRE_PRED_SIZE];
- float speed[SPEED_PERCENTILES];
-} ModelData;
-
-#endif
diff --git a/selfdrive/common/params.cc b/selfdrive/common/params.cc
index 5ab2eae349..4d9c214d37 100644
--- a/selfdrive/common/params.cc
+++ b/selfdrive/common/params.cc
@@ -13,6 +13,7 @@
#include