Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3dcc048299 |
-19
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
Checks: '
|
|
||||||
bugprone-*,
|
|
||||||
-bugprone-integer-division,
|
|
||||||
-bugprone-narrowing-conversions,
|
|
||||||
performance-*,
|
|
||||||
clang-analyzer-*,
|
|
||||||
misc-*,
|
|
||||||
-misc-unused-parameters,
|
|
||||||
modernize-*,
|
|
||||||
-modernize-avoid-c-arrays,
|
|
||||||
-modernize-deprecated-headers,
|
|
||||||
-modernize-use-auto,
|
|
||||||
-modernize-use-using,
|
|
||||||
-modernize-use-nullptr,
|
|
||||||
-modernize-use-trailing-return-type,
|
|
||||||
'
|
|
||||||
CheckOptions:
|
|
||||||
...
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
Wen
|
||||||
|
REGIST
|
||||||
|
PullRequest
|
||||||
|
cancelled
|
||||||
|
FOF
|
||||||
|
NoO
|
||||||
@@ -13,27 +13,6 @@
|
|||||||
*.o-*
|
*.o-*
|
||||||
*.os
|
*.os
|
||||||
*.os-*
|
*.os-*
|
||||||
*.so
|
|
||||||
*.a
|
|
||||||
|
|
||||||
venv/
|
venv/
|
||||||
.venv/
|
.venv/
|
||||||
|
|
||||||
notebooks
|
|
||||||
phone
|
|
||||||
massivemap
|
|
||||||
neos
|
|
||||||
installer
|
|
||||||
chffr/app2
|
|
||||||
chffr/backend/env
|
|
||||||
selfdrive/nav
|
|
||||||
selfdrive/baseui
|
|
||||||
selfdrive/test/simulator2
|
|
||||||
**/cache_data
|
|
||||||
xx/plus
|
|
||||||
xx/community
|
|
||||||
xx/projects
|
|
||||||
!xx/projects/eon_testing_master
|
|
||||||
!xx/projects/map3d
|
|
||||||
xx/ops
|
|
||||||
xx/junk
|
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ end_of_line = lf
|
|||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
[{*.py, *.pyx, *.pxd}]
|
[*.{py,pyx,pxd}]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
* @sunnypilot/dev-internal
|
||||||
|
/.github/ @devtekve @sunnyhaibin
|
||||||
|
/release/ci/ @devtekve @sunnyhaibin
|
||||||
|
/tinygrad_repo @devtekve @Discountchubbs
|
||||||
|
/tinygrad/ @devtekve @Discountchubbs
|
||||||
|
/selfdrive/controls/lib/longitudinal_planner.py @devtekve @Discountchubbs
|
||||||
|
/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py @devtekve @Discountchubbs
|
||||||
|
/selfdrive/modeld/ @devtekve @Discountchubbs
|
||||||
|
/sunnypilot/model* @devtekve @Discountchubbs
|
||||||
|
/sunnypilot/sunnylink/ @devtekve
|
||||||
|
/system/athena/ @devtekve
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
---
|
|
||||||
name: Enhancement
|
|
||||||
about: For openpilot enhancement suggestions
|
|
||||||
title: ''
|
|
||||||
labels: 'enhancement'
|
|
||||||
assignees: ''
|
|
||||||
---
|
|
||||||
|
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
CI / testing:
|
ci:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-all-files: "{.github/**,**/test_*,Jenkinsfile}"
|
- any-glob-to-all-files: "{.github/**,**/test_*,**/test/**,Jenkinsfile}"
|
||||||
|
|
||||||
|
chore:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-all-files: "{.github/**}"
|
||||||
|
|
||||||
car:
|
car:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
@@ -12,7 +16,7 @@ simulation:
|
|||||||
|
|
||||||
ui:
|
ui:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-all-files: 'selfdrive/ui/**'
|
- any-glob-to-all-files: '{selfdrive/assets/**,selfdrive/ui/**,system/ui/**}'
|
||||||
|
|
||||||
tools:
|
tools:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
@@ -24,4 +28,4 @@ multilanguage:
|
|||||||
|
|
||||||
autonomy:
|
autonomy:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-all-files: "{selfdrive/modeld/models/**,selfdrive/test/process_replay/model_replay_ref_commit}"
|
- any-glob-to-all-files: "{selfdrive/modeld/models/**,selfdrive/test/process_replay/model_replay_ref_commit,sunnypilot/modeld*/models/**}"
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
exclude-labels:
|
||||||
|
- 'no-changelog'
|
||||||
|
categories:
|
||||||
|
- title: '🚀 Features'
|
||||||
|
labels:
|
||||||
|
- 'feature'
|
||||||
|
- 'enhancement'
|
||||||
|
- title: '🐛 Bug Fixes'
|
||||||
|
collapse-after: 5
|
||||||
|
labels:
|
||||||
|
- 'fix'
|
||||||
|
- 'bugfix'
|
||||||
|
- 'bug'
|
||||||
|
- title: '🧰 Maintenance'
|
||||||
|
collapse-after: 5
|
||||||
|
label: 'chore'
|
||||||
|
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||||
|
change-title-escapes: '\<*_&'
|
||||||
|
replacers:
|
||||||
|
- search: '/[Ss][Uu][Nn][Nn][Yy][Pp][Ii][Ll][Oo][Tt]/g'
|
||||||
|
replace: 'sunnypilot'
|
||||||
|
- search: '/\b[Ss][Pp]\b/g'
|
||||||
|
replace: 'SP'
|
||||||
|
version-resolver:
|
||||||
|
major:
|
||||||
|
labels:
|
||||||
|
- 'major'
|
||||||
|
minor:
|
||||||
|
labels:
|
||||||
|
- 'minor'
|
||||||
|
patch:
|
||||||
|
labels:
|
||||||
|
- 'patch'
|
||||||
|
default: patch
|
||||||
|
name-template: 'v$RESOLVED_VERSION 🚀'
|
||||||
|
tag-template: 'v$RESOLVED_VERSION'
|
||||||
|
version-template: "0.$MAJOR.$MINOR.$PATCH" # The day OP becomes v1, we need to bump this
|
||||||
|
tag-prefix: "v0." # The day OP becomes v1, we need to bump this
|
||||||
|
prerelease-identifier: "staging"
|
||||||
|
template: |
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
$CHANGES
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
name: 'automatically cache based on current runner'
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
path:
|
|
||||||
description: 'path to cache'
|
|
||||||
required: true
|
|
||||||
key:
|
|
||||||
description: 'key'
|
|
||||||
required: true
|
|
||||||
restore-keys:
|
|
||||||
description: 'restore-keys'
|
|
||||||
required: true
|
|
||||||
save:
|
|
||||||
description: 'whether to save the cache'
|
|
||||||
default: 'false'
|
|
||||||
required: false
|
|
||||||
outputs:
|
|
||||||
cache-hit:
|
|
||||||
description: 'cache hit occurred'
|
|
||||||
value: ${{ (contains(runner.name, 'nsc') && steps.ns-cache.outputs.cache-hit) ||
|
|
||||||
(!contains(runner.name, 'nsc') && inputs.save != 'false' && steps.gha-cache.outputs.cache-hit) ||
|
|
||||||
(!contains(runner.name, 'nsc') && inputs.save == 'false' && steps.gha-cache-ro.outputs.cache-hit) }}
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- name: setup namespace cache
|
|
||||||
id: ns-cache
|
|
||||||
if: ${{ contains(runner.name, 'nsc') }}
|
|
||||||
uses: namespacelabs/nscloud-cache-action@v1
|
|
||||||
with:
|
|
||||||
path: ${{ inputs.path }}
|
|
||||||
|
|
||||||
- name: setup github cache
|
|
||||||
id: gha-cache
|
|
||||||
if: ${{ !contains(runner.name, 'nsc') && inputs.save != 'false' }}
|
|
||||||
uses: 'actions/cache@v4'
|
|
||||||
with:
|
|
||||||
path: ${{ inputs.path }}
|
|
||||||
key: ${{ inputs.key }}
|
|
||||||
restore-keys: ${{ inputs.restore-keys }}
|
|
||||||
|
|
||||||
- name: setup github cache
|
|
||||||
id: gha-cache-ro
|
|
||||||
if: ${{ !contains(runner.name, 'nsc') && inputs.save == 'false' }}
|
|
||||||
uses: 'actions/cache/restore@v4'
|
|
||||||
with:
|
|
||||||
path: ${{ inputs.path }}
|
|
||||||
key: ${{ inputs.key }}
|
|
||||||
restore-keys: ${{ inputs.restore-keys }}
|
|
||||||
|
|
||||||
# make the directory manually in case we didn't get a hit, so it doesn't fail on future steps
|
|
||||||
- id: scons-cache-setup
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ inputs.path }}
|
|
||||||
sudo chmod -R 777 ${{ inputs.path }}
|
|
||||||
sudo chown -R $USER ${{ inputs.path }}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
name: "PR review"
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, reopened, synchronize, edited, edited]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
labeler:
|
|
||||||
name: review
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: false
|
|
||||||
|
|
||||||
# Label PRs
|
|
||||||
- uses: actions/labeler@v5.0.0
|
|
||||||
with:
|
|
||||||
dot: true
|
|
||||||
configuration-path: .github/labeler.yaml
|
|
||||||
|
|
||||||
# Check PR target branch
|
|
||||||
- name: check branch
|
|
||||||
uses: Vankka/pr-target-branch-action@def32ec9d93514138d6ac0132ee62e120a72aed5
|
|
||||||
if: github.repository == 'commaai/openpilot'
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
target: /^(?!master$).*/
|
|
||||||
exclude: /commaai:.*/
|
|
||||||
change-to: ${{ github.base_ref }}
|
|
||||||
already-exists-action: close_this
|
|
||||||
already-exists-comment: "Your PR should be made against the `master` branch"
|
|
||||||
|
|
||||||
# Welcome comment
|
|
||||||
- name: "First timers PR"
|
|
||||||
uses: actions/first-interaction@v1
|
|
||||||
if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot'
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
pr-message: |
|
|
||||||
<!-- _(run_id **${{ github.run_id }}**)_ -->
|
|
||||||
Thanks for contributing to openpilot! In order for us to review your PR as quickly as possible, check the following:
|
|
||||||
* Convert your PR to a draft unless it's ready to review
|
|
||||||
* Read the [contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md)
|
|
||||||
* Before marking as "ready for review", ensure:
|
|
||||||
* the goal is clearly stated in the description
|
|
||||||
* all the tests are passing
|
|
||||||
* the change is [something we merge](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md#what-gets-merged)
|
|
||||||
* include a route or your device' dongle ID if relevant
|
|
||||||
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
name: badges
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 * * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
BASE_IMAGE: openpilot-base
|
|
||||||
DOCKER_REGISTRY: ghcr.io/commaai
|
|
||||||
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $DOCKER_REGISTRY/$BASE_IMAGE:latest /bin/bash -c
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
badges:
|
|
||||||
name: create badges
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'commaai/openpilot'
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- name: Push badges
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "scons -j$(nproc) && python3 selfdrive/ui/translations/create_badges.py"
|
|
||||||
|
|
||||||
rm .gitattributes
|
|
||||||
|
|
||||||
git checkout --orphan badges
|
|
||||||
git rm -rf --cached .
|
|
||||||
git config user.email "badge-researcher@comma.ai"
|
|
||||||
git config user.name "Badge Researcher"
|
|
||||||
|
|
||||||
git add translation_badge.svg
|
|
||||||
git commit -m "Add/Update badges"
|
|
||||||
git push -f origin HEAD
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
name: weekly CI test report
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '37 9 * * 1' # 9:37AM UTC -> 2:37AM PST every monday
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
ci_runs:
|
|
||||||
description: 'The amount of runs to trigger in CI test report'
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
CI_RUNS: ${{ github.event.inputs.ci_runs || '50' }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup:
|
|
||||||
if: github.repository == 'commaai/openpilot'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
ci_runs: ${{ steps.ci_runs_setup.outputs.matrix }}
|
|
||||||
steps:
|
|
||||||
- id: ci_runs_setup
|
|
||||||
name: CI_RUNS=${{ env.CI_RUNS }}
|
|
||||||
run: |
|
|
||||||
matrix=$(python3 -c "import json; print(json.dumps({ 'run_number' : list(range(${{ env.CI_RUNS }})) }))")
|
|
||||||
echo "matrix=$matrix" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
ci_matrix_run:
|
|
||||||
needs: [ setup ]
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix: ${{fromJSON(needs.setup.outputs.ci_runs)}}
|
|
||||||
uses: commaai/openpilot/.github/workflows/ci_weekly_run.yaml@master
|
|
||||||
with:
|
|
||||||
run_number: ${{ matrix.run_number }}
|
|
||||||
|
|
||||||
report:
|
|
||||||
needs: [ci_matrix_run]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: always()
|
|
||||||
steps:
|
|
||||||
- name: Get job results
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
id: get-job-results
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const jobs = await github
|
|
||||||
.paginate("GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt}/jobs", {
|
|
||||||
owner: "commaai",
|
|
||||||
repo: "${{ github.event.repository.name }}",
|
|
||||||
run_id: "${{ github.run_id }}",
|
|
||||||
attempt: "${{ github.run_attempt }}",
|
|
||||||
})
|
|
||||||
var report = {}
|
|
||||||
jobs.slice(1, jobs.length-1).forEach(job => {
|
|
||||||
if (job.conclusion === "skipped") return;
|
|
||||||
const jobName = job.name.split(" / ")[2];
|
|
||||||
const runRegex = /\((.*?)\)/;
|
|
||||||
const run = job.name.match(runRegex)[1];
|
|
||||||
report[jobName] = report[jobName] || { successes: [], failures: [], canceled: [] };
|
|
||||||
switch (job.conclusion) {
|
|
||||||
case "success":
|
|
||||||
report[jobName].successes.push({ "run_number": run, "link": job.html_url}); break;
|
|
||||||
case "failure":
|
|
||||||
report[jobName].failures.push({ "run_number": run, "link": job.html_url }); break;
|
|
||||||
case "canceled":
|
|
||||||
report[jobName].canceled.push({ "run_number": run, "link": job.html_url }); break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return JSON.stringify({"jobs": report});
|
|
||||||
|
|
||||||
- name: Add job results to summary
|
|
||||||
env:
|
|
||||||
JOB_RESULTS: ${{ fromJSON(steps.get-job-results.outputs.result) }}
|
|
||||||
run: |
|
|
||||||
cat <<EOF >> template.html
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
<th>Job</th>
|
|
||||||
<th>✅ Passing</th>
|
|
||||||
<th>❌ Failure Details</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for key in jobs.keys() %}<tr>
|
|
||||||
<td>{% for i in range(5) %}{% if i+1 <= (5 * jobs[key]["successes"]|length // ${{ env.CI_RUNS }}) %}🟩{% else %}🟥{% endif %}{% endfor%}</td>
|
|
||||||
<td>{{ key }}</td>
|
|
||||||
<td>{{ 100 * jobs[key]["successes"]|length // ${{ env.CI_RUNS }} }}%</td>
|
|
||||||
<td>{% if jobs[key]["failures"]|length > 0 %}<details>{% for failure in jobs[key]["failures"] %}<a href="{{ failure['link'] }}">Log for run #{{ failure['run_number'] }}</a><br>{% endfor %}</details>{% else %}{% endif %}</td>
|
|
||||||
</td>
|
|
||||||
</tr>{% endfor %}
|
|
||||||
</table>
|
|
||||||
EOF
|
|
||||||
|
|
||||||
pip install jinja2-cli
|
|
||||||
echo $JOB_RESULTS | jinja2 template.html > report.html
|
|
||||||
echo "# CI Test Report - ${{ env.CI_RUNS }} Runs" >> $GITHUB_STEP_SUMMARY
|
|
||||||
cat report.html >> $GITHUB_STEP_SUMMARY
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
name: weekly CI test run
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
run_number:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-run-${{ inputs.run_number }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
selfdrive_tests:
|
|
||||||
uses: commaai/openpilot/.github/workflows/selfdrive_tests.yaml@master
|
|
||||||
with:
|
|
||||||
run_number: ${{ inputs.run_number }}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
name: 'compile openpilot'
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- shell: bash
|
|
||||||
name: Build openpilot with all flags
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "scons -j$(nproc)"
|
|
||||||
${{ env.RUN }} "release/check-dirty.sh"
|
|
||||||
- shell: bash
|
|
||||||
name: Cleanup scons cache and rebuild
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "rm -rf /tmp/scons_cache/* && \
|
|
||||||
scons -j$(nproc) --cache-populate"
|
|
||||||
- name: Save scons cache
|
|
||||||
uses: actions/cache/save@v4
|
|
||||||
if: github.ref == 'refs/heads/master'
|
|
||||||
with:
|
|
||||||
path: .ci_cache/scons_cache
|
|
||||||
key: scons-${{ runner.arch }}-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
name: docs
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
run_number:
|
|
||||||
default: '1'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
concurrency:
|
|
||||||
group: docs-tests-ci-run-${{ inputs.run_number }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
docs:
|
|
||||||
name: build docs
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: commaai/timeout@v1
|
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
|
|
||||||
# Build
|
|
||||||
- name: Build docs
|
|
||||||
run: |
|
|
||||||
# TODO: can we install just the "docs" dependency group without the normal deps?
|
|
||||||
pip install mkdocs
|
|
||||||
mkdocs build
|
|
||||||
|
|
||||||
# Push to docs.comma.ai
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
if: github.ref == 'refs/heads/master' && github.repository == 'commaai/openpilot'
|
|
||||||
with:
|
|
||||||
path: openpilot-docs
|
|
||||||
ssh-key: ${{ secrets.OPENPILOT_DOCS_KEY }}
|
|
||||||
repository: commaai/openpilot-docs
|
|
||||||
- name: Push
|
|
||||||
if: github.ref == 'refs/heads/master' && github.repository == 'commaai/openpilot'
|
|
||||||
run: |
|
|
||||||
set -x
|
|
||||||
|
|
||||||
source release/identity.sh
|
|
||||||
|
|
||||||
cd openpilot-docs
|
|
||||||
git checkout --orphan tmp
|
|
||||||
git rm -rf .
|
|
||||||
|
|
||||||
# copy over docs
|
|
||||||
cp -r ../docs_site/ docs/
|
|
||||||
|
|
||||||
# GitHub pages config
|
|
||||||
touch docs/.nojekyll
|
|
||||||
echo -n docs.comma.ai > docs/CNAME
|
|
||||||
|
|
||||||
git add -f .
|
|
||||||
git commit -m "build docs"
|
|
||||||
|
|
||||||
# docs live in different repo to not bloat openpilot's full clone size
|
|
||||||
git push -f origin tmp:gh-pages
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
name: jenkins scan
|
|
||||||
|
|
||||||
on:
|
|
||||||
issue_comment:
|
|
||||||
types: [created, edited]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# TODO: gc old branches in a separate job in this workflow
|
|
||||||
scan-comments:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ github.event.issue.pull_request }}
|
|
||||||
steps:
|
|
||||||
- name: Check for trigger phrase
|
|
||||||
id: check_comment
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const triggerPhrase = "trigger-jenkins";
|
|
||||||
const comment = context.payload.comment.body;
|
|
||||||
const commenter = context.payload.comment.user.login;
|
|
||||||
|
|
||||||
const { data: permissions } = await github.rest.repos.getCollaboratorPermissionLevel({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
username: commenter
|
|
||||||
});
|
|
||||||
|
|
||||||
const hasWriteAccess = permissions.permission === 'write' || permissions.permission === 'admin';
|
|
||||||
|
|
||||||
return (hasWriteAccess && comment.includes(triggerPhrase));
|
|
||||||
result-encoding: json
|
|
||||||
|
|
||||||
- name: Checkout repository
|
|
||||||
if: steps.check_comment.outputs.result == 'true'
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: refs/pull/${{ github.event.issue.number }}/head
|
|
||||||
|
|
||||||
- name: Push to tmp-jenkins branch
|
|
||||||
if: steps.check_comment.outputs.result == 'true'
|
|
||||||
run: |
|
|
||||||
git config --global user.name "github-actions[bot]"
|
|
||||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git checkout -b tmp-jenkins-${{ github.event.issue.number }}
|
|
||||||
GIT_LFS_SKIP_PUSH=1 git push -f origin tmp-jenkins-${{ github.event.issue.number }}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
name: prebuilt
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 * * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
BUILD: selfdrive/test/docker_build.sh prebuilt
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build_prebuilt:
|
|
||||||
name: build prebuilt
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'commaai/openpilot'
|
|
||||||
env:
|
|
||||||
PUSH_IMAGE: true
|
|
||||||
permissions:
|
|
||||||
checks: read
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
steps:
|
|
||||||
- name: Wait for green check mark
|
|
||||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
|
||||||
uses: lewagon/wait-on-check-action@ccfb013c15c8afb7bf2b7c028fb74dc5a068cccc
|
|
||||||
with:
|
|
||||||
ref: master
|
|
||||||
wait-interval: 30
|
|
||||||
running-workflow-name: 'build prebuilt'
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
check-regexp: ^((?!.*(build master-ci).*).)*$
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- run: git lfs pull
|
|
||||||
- name: Build and Push docker image
|
|
||||||
run: |
|
|
||||||
$DOCKER_LOGIN
|
|
||||||
eval "$BUILD"
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
name: release
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 9 * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build_masterci:
|
|
||||||
name: build master-ci
|
|
||||||
env:
|
|
||||||
TARGET_DIR: /tmp/openpilot
|
|
||||||
ImageOS: ubuntu20
|
|
||||||
container:
|
|
||||||
image: ghcr.io/commaai/openpilot-base:latest
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'commaai/openpilot'
|
|
||||||
permissions:
|
|
||||||
checks: read
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- name: Install wait-on-check-action dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libyaml-dev
|
|
||||||
- name: Wait for green check mark
|
|
||||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
|
||||||
uses: lewagon/wait-on-check-action@ccfb013c15c8afb7bf2b7c028fb74dc5a068cccc
|
|
||||||
with:
|
|
||||||
ref: master
|
|
||||||
wait-interval: 30
|
|
||||||
running-workflow-name: 'build master-ci'
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
check-regexp: ^((?!.*(build prebuilt).*).)*$
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Pull LFS
|
|
||||||
run: |
|
|
||||||
git config --global --add safe.directory '*'
|
|
||||||
git lfs pull
|
|
||||||
- name: Build master-ci
|
|
||||||
run: |
|
|
||||||
release/build_devel.sh
|
|
||||||
- name: Run tests
|
|
||||||
run: |
|
|
||||||
export PYTHONPATH=$TARGET_DIR
|
|
||||||
cd $TARGET_DIR
|
|
||||||
scons -j$(nproc)
|
|
||||||
pytest -n logical selfdrive/car/tests/test_car_interfaces.py
|
|
||||||
- name: Push master-ci
|
|
||||||
run: |
|
|
||||||
unset TARGET_DIR
|
|
||||||
BRANCH=__nightly release/build_devel.sh
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
name: repo maintenance
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 14 * * 1" # every Monday at 2am UTC (6am PST)
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
BASE_IMAGE: openpilot-base
|
|
||||||
BUILD: selfdrive/test/docker_build.sh base
|
|
||||||
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e CI=1 -e PYTHONWARNINGS=error -e FILEREADER_CACHE=1 -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $BASE_IMAGE /bin/bash -c
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update_translations:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'commaai/openpilot'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- name: Update translations
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "python3 selfdrive/ui/update_translations.py --vanish"
|
|
||||||
- name: Create Pull Request
|
|
||||||
uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83
|
|
||||||
with:
|
|
||||||
author: Vehicle Researcher <user@comma.ai>
|
|
||||||
commit-message: "Update translations"
|
|
||||||
title: "[bot] Update translations"
|
|
||||||
body: "Automatic PR from repo-maintenance -> update_translations"
|
|
||||||
branch: "update-translations"
|
|
||||||
base: "master"
|
|
||||||
delete-branch: true
|
|
||||||
labels: bot
|
|
||||||
|
|
||||||
package_updates:
|
|
||||||
name: package_updates
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: ghcr.io/commaai/openpilot-base:latest
|
|
||||||
if: github.repository == 'commaai/openpilot'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- name: uv lock
|
|
||||||
run: |
|
|
||||||
python3 -m ensurepip --upgrade
|
|
||||||
pip3 install uv
|
|
||||||
uv lock --upgrade
|
|
||||||
- name: bump submodules
|
|
||||||
run: |
|
|
||||||
git config --global --add safe.directory '*'
|
|
||||||
git -c submodule."tinygrad".update=none submodule update --remote
|
|
||||||
git add .
|
|
||||||
- name: update car docs
|
|
||||||
run: |
|
|
||||||
scons -j$(nproc) --minimal opendbc_repo
|
|
||||||
PYTHONPATH=. python selfdrive/car/docs.py
|
|
||||||
git add docs/CARS.md
|
|
||||||
- name: Create Pull Request
|
|
||||||
uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83
|
|
||||||
with:
|
|
||||||
author: Vehicle Researcher <user@comma.ai>
|
|
||||||
token: ${{ secrets.ACTIONS_CREATE_PR_PAT }}
|
|
||||||
commit-message: Update Python packages
|
|
||||||
title: '[bot] Update Python packages'
|
|
||||||
branch: auto-package-updates
|
|
||||||
base: master
|
|
||||||
delete-branch: true
|
|
||||||
body: 'Automatic PR from repo-maintenance -> package_updates'
|
|
||||||
labels: bot
|
|
||||||
@@ -1,350 +0,0 @@
|
|||||||
name: selfdrive
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
workflow_dispatch:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
run_number:
|
|
||||||
default: '1'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: selfdrive-tests-ci-run-${{ inputs.run_number }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
PYTHONWARNINGS: error
|
|
||||||
BASE_IMAGE: openpilot-base
|
|
||||||
AZURE_TOKEN: ${{ secrets.AZURE_COMMADATACI_OPENPILOTCI_TOKEN }}
|
|
||||||
|
|
||||||
DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
BUILD: selfdrive/test/docker_build.sh base
|
|
||||||
|
|
||||||
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e CI=1 -e PYTHONWARNINGS=error -e FILEREADER_CACHE=1 -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $BASE_IMAGE /bin/bash -c
|
|
||||||
|
|
||||||
PYTEST: pytest --continue-on-collection-errors --cov --cov-report=xml --cov-append --durations=0 --durations-min=5 --hypothesis-seed 0 -n logical
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build_release:
|
|
||||||
name: build release
|
|
||||||
runs-on:
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
|
|
||||||
env:
|
|
||||||
STRIPPED_DIR: /tmp/releasepilot
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- name: Getting LFS files
|
|
||||||
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e
|
|
||||||
with:
|
|
||||||
timeout_minutes: 2
|
|
||||||
max_attempts: 3
|
|
||||||
command: git lfs pull
|
|
||||||
- name: Build devel
|
|
||||||
timeout-minutes: 1
|
|
||||||
run: TARGET_DIR=$STRIPPED_DIR release/build_devel.sh
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- name: Check submodules
|
|
||||||
if: github.repository == 'commaai/openpilot'
|
|
||||||
timeout-minutes: 3
|
|
||||||
run: release/check-submodules.sh
|
|
||||||
- name: Build openpilot and run checks
|
|
||||||
timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 10 || 30) }} # allow more time when we missed the scons cache
|
|
||||||
run: |
|
|
||||||
cd $STRIPPED_DIR
|
|
||||||
${{ env.RUN }} "python3 system/manager/build.py"
|
|
||||||
- name: Run tests
|
|
||||||
timeout-minutes: 1
|
|
||||||
run: |
|
|
||||||
cd $STRIPPED_DIR
|
|
||||||
${{ env.RUN }} "release/check-dirty.sh"
|
|
||||||
|
|
||||||
build:
|
|
||||||
runs-on:
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- name: Setup docker push
|
|
||||||
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot'
|
|
||||||
run: |
|
|
||||||
echo "PUSH_IMAGE=true" >> "$GITHUB_ENV"
|
|
||||||
$DOCKER_LOGIN
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- uses: ./.github/workflows/compile-openpilot
|
|
||||||
timeout-minutes: 30
|
|
||||||
|
|
||||||
build_mac:
|
|
||||||
name: build macOS
|
|
||||||
runs-on: ${{ github.repository == 'commaai/openpilot' && 'namespace-profile-macos-8x14' || 'macos-latest' }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- name: Homebrew cache
|
|
||||||
uses: ./.github/workflows/auto-cache
|
|
||||||
with:
|
|
||||||
path: ~/Library/Caches/Homebrew
|
|
||||||
- name: Install dependencies
|
|
||||||
run: ./tools/mac_setup.sh
|
|
||||||
env:
|
|
||||||
# package install has DeprecationWarnings
|
|
||||||
PYTHONWARNINGS: default
|
|
||||||
- run: git lfs pull
|
|
||||||
- run: echo "CACHE_COMMIT_DATE=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d-%H:%M')" >> $GITHUB_ENV
|
|
||||||
- name: Getting scons cache
|
|
||||||
uses: ./.github/workflows/auto-cache
|
|
||||||
with:
|
|
||||||
path: /tmp/scons_cache
|
|
||||||
- name: Building openpilot
|
|
||||||
run: . .venv/bin/activate && scons -j$(nproc)
|
|
||||||
|
|
||||||
static_analysis:
|
|
||||||
name: static analysis
|
|
||||||
runs-on:
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
|
|
||||||
env:
|
|
||||||
PYTHONWARNINGS: default
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- name: Static analysis
|
|
||||||
timeout-minutes: 1
|
|
||||||
run: ${{ env.RUN }} "scripts/lint/lint.sh"
|
|
||||||
|
|
||||||
unit_tests:
|
|
||||||
name: unit tests
|
|
||||||
runs-on:
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- name: Build openpilot
|
|
||||||
run: ${{ env.RUN }} "scons -j$(nproc)"
|
|
||||||
- name: Run unit tests
|
|
||||||
timeout-minutes: ${{ contains(runner.name, 'nsc') && 1 || 20 }}
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "$PYTEST --collect-only -m 'not slow' &> /dev/null && \
|
|
||||||
MAX_EXAMPLES=1 $PYTEST -m 'not slow' && \
|
|
||||||
./selfdrive/ui/tests/create_test_translations.sh && \
|
|
||||||
QT_QPA_PLATFORM=offscreen ./selfdrive/ui/tests/test_translations && \
|
|
||||||
chmod -R 777 /tmp/comma_download_cache"
|
|
||||||
- name: "Upload coverage to Codecov"
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
name: ${{ github.job }}
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
process_replay:
|
|
||||||
name: process replay
|
|
||||||
runs-on:
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- name: Cache test routes
|
|
||||||
id: dependency-cache
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: .ci_cache/comma_download_cache
|
|
||||||
key: proc-replay-${{ hashFiles('selfdrive/test/process_replay/ref_commit', 'selfdrive/test/process_replay/test_processes.py') }}
|
|
||||||
- name: Build openpilot
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "scons -j$(nproc)"
|
|
||||||
- name: Run replay
|
|
||||||
timeout-minutes: ${{ contains(runner.name, 'nsc') && (steps.dependency-cache.outputs.cache-hit == 'true') && 1 || 20 }}
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "coverage run selfdrive/test/process_replay/test_processes.py -j$(nproc) && \
|
|
||||||
chmod -R 777 /tmp/comma_download_cache && \
|
|
||||||
coverage combine && \
|
|
||||||
coverage xml"
|
|
||||||
- name: Print diff
|
|
||||||
id: print-diff
|
|
||||||
if: always()
|
|
||||||
run: cat selfdrive/test/process_replay/diff.txt
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
if: always()
|
|
||||||
continue-on-error: true
|
|
||||||
with:
|
|
||||||
name: process_replay_diff.txt
|
|
||||||
path: selfdrive/test/process_replay/diff.txt
|
|
||||||
- name: Upload reference logs
|
|
||||||
if: ${{ failure() && steps.print-diff.outcome == 'success' && github.repository == 'commaai/openpilot' && env.AZURE_TOKEN != '' }}
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "unset PYTHONWARNINGS && AZURE_TOKEN='$AZURE_TOKEN' python3 selfdrive/test/process_replay/test_processes.py -j$(nproc) --upload-only"
|
|
||||||
- name: Run regen
|
|
||||||
if: false
|
|
||||||
timeout-minutes: 4
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "ONNXCPU=1 $PYTEST selfdrive/test/process_replay/test_regen.py && \
|
|
||||||
chmod -R 777 /tmp/comma_download_cache"
|
|
||||||
- name: "Upload coverage to Codecov"
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
name: ${{ github.job }}
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
test_cars:
|
|
||||||
name: cars
|
|
||||||
runs-on:
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
job: [0, 1, 2, 3]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- name: Cache test routes
|
|
||||||
id: routes-cache
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: .ci_cache/comma_download_cache
|
|
||||||
key: car_models-${{ hashFiles('selfdrive/car/tests/test_models.py', 'opendbc/car/tests/routes.py') }}-${{ matrix.job }}
|
|
||||||
- name: Build openpilot
|
|
||||||
run: ${{ env.RUN }} "scons -j$(nproc)"
|
|
||||||
- name: Test car models
|
|
||||||
timeout-minutes: ${{ contains(runner.name, 'nsc') && (steps.routes-cache.outputs.cache-hit == 'true') && 1 || 20 }}
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "MAX_EXAMPLES=1 $PYTEST selfdrive/car/tests/test_models.py && \
|
|
||||||
chmod -R 777 /tmp/comma_download_cache"
|
|
||||||
env:
|
|
||||||
NUM_JOBS: 4
|
|
||||||
JOB_ID: ${{ matrix.job }}
|
|
||||||
- name: "Upload coverage to Codecov"
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
name: ${{ github.job }}-${{ matrix.job }}
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
car_docs_diff:
|
|
||||||
name: PR comments
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
#if: github.event_name == 'pull_request'
|
|
||||||
if: false # TODO: run this in opendbc?
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
ref: ${{ github.event.pull_request.base.ref }}
|
|
||||||
- run: git lfs pull
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- name: Get base car info
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "scons -j$(nproc) && python3 selfdrive/debug/dump_car_docs.py --path /tmp/openpilot_cache/base_car_docs"
|
|
||||||
sudo chown -R $USER:$USER ${{ github.workspace }}
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
path: current
|
|
||||||
- run: cd current && git lfs pull
|
|
||||||
- name: Save car docs diff
|
|
||||||
id: save_diff
|
|
||||||
run: |
|
|
||||||
cd current
|
|
||||||
${{ env.RUN }} "scons -j$(nproc)"
|
|
||||||
output=$(${{ env.RUN }} "python3 selfdrive/debug/print_docs_diff.py --path /tmp/openpilot_cache/base_car_docs")
|
|
||||||
output="${output//$'\n'/'%0A'}"
|
|
||||||
echo "::set-output name=diff::$output"
|
|
||||||
- name: Find comment
|
|
||||||
if: ${{ env.AZURE_TOKEN != '' }}
|
|
||||||
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e
|
|
||||||
id: fc
|
|
||||||
with:
|
|
||||||
issue-number: ${{ github.event.pull_request.number }}
|
|
||||||
body-includes: This PR makes changes to
|
|
||||||
- name: Update comment
|
|
||||||
if: ${{ steps.save_diff.outputs.diff != '' && env.AZURE_TOKEN != '' }}
|
|
||||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043
|
|
||||||
with:
|
|
||||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
|
||||||
issue-number: ${{ github.event.pull_request.number }}
|
|
||||||
body: "${{ steps.save_diff.outputs.diff }}"
|
|
||||||
edit-mode: replace
|
|
||||||
- name: Delete comment
|
|
||||||
if: ${{ steps.fc.outputs.comment-id != '' && steps.save_diff.outputs.diff == '' && env.AZURE_TOKEN != '' }}
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
github.rest.issues.deleteComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
comment_id: ${{ steps.fc.outputs.comment-id }}
|
|
||||||
})
|
|
||||||
|
|
||||||
simulator_driving:
|
|
||||||
name: simulator driving
|
|
||||||
runs-on:
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
|
|
||||||
if: (github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- name: Build openpilot
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "scons -j$(nproc)"
|
|
||||||
- name: Driving test
|
|
||||||
timeout-minutes: 1
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "source selfdrive/test/setup_xvfb.sh && \
|
|
||||||
source selfdrive/test/setup_vsound.sh && \
|
|
||||||
CI=1 pytest -s tools/sim/tests/test_metadrive_bridge.py"
|
|
||||||
|
|
||||||
create_ui_report:
|
|
||||||
# This job name needs to be the same as UI_JOB_NAME in ui_preview.yaml
|
|
||||||
name: Create UI Report
|
|
||||||
runs-on:
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
|
|
||||||
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- name: caching frames
|
|
||||||
id: frames-cache
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: .ci_cache/comma_download_cache
|
|
||||||
key: ui_screenshots_test_${{ hashFiles('selfdrive/ui/tests/test_ui/run.py') }}
|
|
||||||
- name: Build openpilot
|
|
||||||
run: ${{ env.RUN }} "scons -j$(nproc)"
|
|
||||||
- name: Create Test Report
|
|
||||||
timeout-minutes: ${{ ((steps.frames-cache.outputs.cache-hit == 'true') && 1 || 3) }}
|
|
||||||
run: >
|
|
||||||
${{ env.RUN }} "PYTHONWARNINGS=ignore &&
|
|
||||||
source selfdrive/test/setup_xvfb.sh &&
|
|
||||||
CACHE_ROOT=/tmp/comma_download_cache python3 selfdrive/ui/tests/test_ui/run.py &&
|
|
||||||
chmod -R 777 /tmp/comma_download_cache"
|
|
||||||
- name: Upload Test Report
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: report-${{ inputs.run_number || '1' }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }}
|
|
||||||
path: selfdrive/ui/tests/test_ui/report_1/screenshots
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
name: 'openpilot env setup, with retry on failure'
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
docker_hub_pat:
|
|
||||||
description: 'Auth token for Docker Hub, required for BuildJet jobs'
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
sleep_time:
|
|
||||||
description: 'Time to sleep between retries'
|
|
||||||
required: false
|
|
||||||
default: 30
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- id: setup1
|
|
||||||
uses: ./.github/workflows/setup
|
|
||||||
continue-on-error: true
|
|
||||||
with:
|
|
||||||
is_retried: true
|
|
||||||
- if: steps.setup1.outcome == 'failure'
|
|
||||||
shell: bash
|
|
||||||
run: sleep ${{ inputs.sleep_time }}
|
|
||||||
- id: setup2
|
|
||||||
if: steps.setup1.outcome == 'failure'
|
|
||||||
uses: ./.github/workflows/setup
|
|
||||||
continue-on-error: true
|
|
||||||
with:
|
|
||||||
is_retried: true
|
|
||||||
- if: steps.setup2.outcome == 'failure'
|
|
||||||
shell: bash
|
|
||||||
run: sleep ${{ inputs.sleep_time }}
|
|
||||||
- id: setup3
|
|
||||||
if: steps.setup2.outcome == 'failure'
|
|
||||||
uses: ./.github/workflows/setup
|
|
||||||
with:
|
|
||||||
is_retried: true
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
name: 'openpilot env setup'
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
is_retried:
|
|
||||||
description: 'A mock param that asserts that we use the setup-with-retry instead of this action directly'
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
# assert that this action is retried using the setup-with-retry
|
|
||||||
- shell: bash
|
|
||||||
if: ${{ inputs.is_retried == 'false' }}
|
|
||||||
run: |
|
|
||||||
echo "You should not run this action directly. Use setup-with-retry instead"
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
- shell: bash
|
|
||||||
name: No retries!
|
|
||||||
run: |
|
|
||||||
if [ "${{ github.run_attempt }}" -gt 1 ]; then
|
|
||||||
echo -e "\033[0;31m##################################################"
|
|
||||||
echo -e "\033[0;31m Retries not allowed! Fix the flaky test! "
|
|
||||||
echo -e "\033[0;31m##################################################\033[0m"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# do this after checkout to ensure our custom LFS config is used to pull from GitLab
|
|
||||||
- shell: bash
|
|
||||||
run: git lfs pull
|
|
||||||
|
|
||||||
# build cache
|
|
||||||
- id: date
|
|
||||||
shell: bash
|
|
||||||
run: echo "CACHE_COMMIT_DATE=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d-%H:%M')" >> $GITHUB_ENV
|
|
||||||
- shell: bash
|
|
||||||
run: echo "$CACHE_COMMIT_DATE"
|
|
||||||
- id: scons-cache
|
|
||||||
uses: ./.github/workflows/auto-cache
|
|
||||||
with:
|
|
||||||
path: .ci_cache/scons_cache
|
|
||||||
key: scons-${{ runner.arch }}-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
|
||||||
restore-keys: |
|
|
||||||
scons-${{ runner.arch }}-${{ env.CACHE_COMMIT_DATE }}
|
|
||||||
scons-${{ runner.arch }}
|
|
||||||
# as suggested here: https://github.com/moby/moby/issues/32816#issuecomment-910030001
|
|
||||||
- id: normalize-file-permissions
|
|
||||||
shell: bash
|
|
||||||
name: Normalize file permissions to ensure a consistent docker build cache
|
|
||||||
run: |
|
|
||||||
find . -type f -executable -not -perm 755 -exec chmod 755 {} \;
|
|
||||||
find . -type f -not -executable -not -perm 644 -exec chmod 644 {} \;
|
|
||||||
# build our docker image
|
|
||||||
- shell: bash
|
|
||||||
run: eval ${{ env.BUILD }}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
name: stale
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '30 1 * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
DAYS_BEFORE_PR_CLOSE: 2
|
|
||||||
DAYS_BEFORE_PR_STALE: 9
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v9
|
|
||||||
with:
|
|
||||||
exempt-all-milestones: true
|
|
||||||
|
|
||||||
# pull request config
|
|
||||||
stale-pr-message: 'This PR has had no activity for ${{ env.DAYS_BEFORE_PR_STALE }} days. It will be automatically closed in ${{ env.DAYS_BEFORE_PR_CLOSE }} days if there is no activity.'
|
|
||||||
close-pr-message: 'This PR has been automatically closed due to inactivity. Feel free to re-open once activity resumes.'
|
|
||||||
stale-pr-label: stale
|
|
||||||
delete-branch: ${{ github.event.pull_request.head.repo.full_name == 'commaai/openpilot' }} # only delete branches on the main repo
|
|
||||||
exempt-pr-labels: "ignore stale,needs testing" # if wip or it needs testing from the community, don't mark as stale
|
|
||||||
days-before-pr-stale: ${{ env.DAYS_BEFORE_PR_STALE }}
|
|
||||||
days-before-pr-close: ${{ env.DAYS_BEFORE_PR_CLOSE }}
|
|
||||||
|
|
||||||
# issue config
|
|
||||||
days-before-issue-stale: -1 # ignore issues for now
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
name: "ui preview"
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request_target:
|
|
||||||
types: [assigned, opened, synchronize, reopened, edited]
|
|
||||||
branches:
|
|
||||||
- 'master'
|
|
||||||
paths:
|
|
||||||
- 'selfdrive/ui/**'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
UI_JOB_NAME: "Create UI Report"
|
|
||||||
REPORT_NAME: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }}
|
|
||||||
SHA: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.sha || github.event.pull_request.head.sha }}
|
|
||||||
BRANCH_NAME: "openpilot/pr-${{ github.event.number }}"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
preview:
|
|
||||||
if: github.repository == 'commaai/openpilot'
|
|
||||||
name: preview
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 20
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
actions: read
|
|
||||||
steps:
|
|
||||||
- name: Waiting for ui generation to start
|
|
||||||
run: sleep 30
|
|
||||||
|
|
||||||
- name: Waiting for ui generation to end
|
|
||||||
uses: lewagon/wait-on-check-action@v1.3.4
|
|
||||||
with:
|
|
||||||
ref: ${{ env.SHA }}
|
|
||||||
check-name: ${{ env.UI_JOB_NAME }}
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
allowed-conclusions: success
|
|
||||||
wait-interval: 20
|
|
||||||
|
|
||||||
- name: Getting workflow run ID
|
|
||||||
id: get_run_id
|
|
||||||
run: |
|
|
||||||
echo "run_id=$(curl https://api.github.com/repos/${{ github.repository }}/commits/${{ env.SHA }}/check-runs | jq -r '.check_runs[] | select(.name == "${{ env.UI_JOB_NAME }}") | .html_url | capture("(?<number>[0-9]+)") | .number')" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Getting proposed ui
|
|
||||||
id: download-artifact
|
|
||||||
uses: dawidd6/action-download-artifact@v6
|
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run_id: ${{ steps.get_run_id.outputs.run_id }}
|
|
||||||
search_artifacts: true
|
|
||||||
name: report-1-${{ env.REPORT_NAME }}
|
|
||||||
path: ${{ github.workspace }}/pr_ui
|
|
||||||
|
|
||||||
- name: Getting master ui
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
repository: commaai/ci-artifacts
|
|
||||||
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
|
|
||||||
path: ${{ github.workspace }}/master_ui
|
|
||||||
ref: openpilot_master_ui
|
|
||||||
|
|
||||||
- name: Saving new master ui
|
|
||||||
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
|
|
||||||
working-directory: ${{ github.workspace }}/master_ui
|
|
||||||
run: |
|
|
||||||
git checkout --orphan=new_master_ui
|
|
||||||
git rm -rf *
|
|
||||||
git branch -D openpilot_master_ui
|
|
||||||
git branch -m openpilot_master_ui
|
|
||||||
git config user.name "GitHub Actions Bot"
|
|
||||||
git config user.email "<>"
|
|
||||||
mv ${{ github.workspace }}/pr_ui/*.png .
|
|
||||||
git add .
|
|
||||||
git commit -m "screenshots for commit ${{ env.SHA }}"
|
|
||||||
git push origin openpilot_master_ui --force
|
|
||||||
|
|
||||||
- name: Finding diff
|
|
||||||
if: github.event_name == 'pull_request_target'
|
|
||||||
id: find_diff
|
|
||||||
run: >-
|
|
||||||
sudo apt-get install -y imagemagick
|
|
||||||
|
|
||||||
scenes=$(find ${{ github.workspace }}/pr_ui/*.png -type f -printf "%f\n" | cut -d '.' -f 1 | grep -v 'pair_device')
|
|
||||||
A=($scenes)
|
|
||||||
|
|
||||||
DIFF=""
|
|
||||||
TABLE="<details><summary>All Screenshots</summary>"
|
|
||||||
TABLE="${TABLE}<table>"
|
|
||||||
|
|
||||||
for ((i=0; i<${#A[*]}; i=i+1));
|
|
||||||
do
|
|
||||||
|
|
||||||
if ! compare -fuzz 2% -highlight-color DeepSkyBlue1 -lowlight-color Black -compose Src ${{ github.workspace }}/master_ui/${A[$i]}.png ${{ github.workspace }}/pr_ui/${A[$i]}.png ${{ github.workspace }}/pr_ui/${A[$i]}_diff.png; then
|
|
||||||
convert ${{ github.workspace }}/pr_ui/${A[$i]}_diff.png -transparent black mask.png
|
|
||||||
composite mask.png ${{ github.workspace }}/master_ui/${A[$i]}.png composite_diff.png
|
|
||||||
convert -delay 100 ${{ github.workspace }}/master_ui/${A[$i]}.png composite_diff.png -loop 0 ${{ github.workspace }}/pr_ui/${A[$i]}_diff.gif
|
|
||||||
|
|
||||||
mv ${{ github.workspace }}/master_ui/${A[$i]}.png ${{ github.workspace }}/pr_ui/${A[$i]}_master_ref.png
|
|
||||||
|
|
||||||
DIFF="${DIFF}<details open>"
|
|
||||||
DIFF="${DIFF}<summary>${A[$i]} : \$\${\\color{red}\\text{DIFFERENT}}\$\$</summary>"
|
|
||||||
DIFF="${DIFF}<table>"
|
|
||||||
|
|
||||||
DIFF="${DIFF}<tr>"
|
|
||||||
DIFF="${DIFF} <td> master <img src=\"https://raw.githubusercontent.com/commaai/ci-artifacts/${{ env.BRANCH_NAME }}/${A[$i]}_master_ref.png\"> </td>"
|
|
||||||
DIFF="${DIFF} <td> proposed <img src=\"https://raw.githubusercontent.com/commaai/ci-artifacts/${{ env.BRANCH_NAME }}/${A[$i]}.png\"> </td>"
|
|
||||||
DIFF="${DIFF}</tr>"
|
|
||||||
|
|
||||||
DIFF="${DIFF}<tr>"
|
|
||||||
DIFF="${DIFF} <td> diff <img src=\"https://raw.githubusercontent.com/commaai/ci-artifacts/${{ env.BRANCH_NAME }}/${A[$i]}_diff.png\"> </td>"
|
|
||||||
DIFF="${DIFF} <td> composite diff <img src=\"https://raw.githubusercontent.com/commaai/ci-artifacts/${{ env.BRANCH_NAME }}/${A[$i]}_diff.gif\"> </td>"
|
|
||||||
DIFF="${DIFF}</tr>"
|
|
||||||
|
|
||||||
DIFF="${DIFF}</table>"
|
|
||||||
DIFF="${DIFF}</details>"
|
|
||||||
else
|
|
||||||
rm -f ${{ github.workspace }}/pr_ui/${A[$i]}_diff.png
|
|
||||||
fi
|
|
||||||
|
|
||||||
INDEX=$(($i % 2))
|
|
||||||
if [[ $INDEX -eq 0 ]]; then
|
|
||||||
TABLE="${TABLE}<tr>"
|
|
||||||
fi
|
|
||||||
TABLE="${TABLE} <td> <img src=\"https://raw.githubusercontent.com/commaai/ci-artifacts/${{ env.BRANCH_NAME }}/${A[$i]}.png\"> </td>"
|
|
||||||
if [[ $INDEX -eq 1 || $(($i + 1)) -eq ${#A[*]} ]]; then
|
|
||||||
TABLE="${TABLE}</tr>"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
TABLE="${TABLE}</table></details>"
|
|
||||||
|
|
||||||
echo "DIFF=$DIFF$TABLE" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Saving proposed ui
|
|
||||||
if: github.event_name == 'pull_request_target'
|
|
||||||
working-directory: ${{ github.workspace }}/master_ui
|
|
||||||
run: |
|
|
||||||
git config user.name "GitHub Actions Bot"
|
|
||||||
git config user.email "<>"
|
|
||||||
git checkout --orphan=${{ env.BRANCH_NAME }}
|
|
||||||
git rm -rf *
|
|
||||||
mv ${{ github.workspace }}/pr_ui/* .
|
|
||||||
git add .
|
|
||||||
git commit -m "screenshots for PR #${{ github.event.number }}"
|
|
||||||
git push origin ${{ env.BRANCH_NAME }} --force
|
|
||||||
|
|
||||||
- name: Comment Screenshots on PR
|
|
||||||
if: github.event_name == 'pull_request_target'
|
|
||||||
uses: thollander/actions-comment-pull-request@v2
|
|
||||||
with:
|
|
||||||
message: |
|
|
||||||
<!-- _(run_id_screenshots **${{ github.run_id }}**)_ -->
|
|
||||||
## UI Preview
|
|
||||||
${{ steps.find_diff.outputs.DIFF }}
|
|
||||||
comment_tag: run_id_screenshots
|
|
||||||
pr_number: ${{ github.event.number }}
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
+28
-38
@@ -10,15 +10,16 @@ venv/
|
|||||||
.overlay_init
|
.overlay_init
|
||||||
.overlay_consistent
|
.overlay_consistent
|
||||||
.sconsign.dblite
|
.sconsign.dblite
|
||||||
model2.png
|
|
||||||
a.out
|
a.out
|
||||||
.hypothesis
|
.hypothesis
|
||||||
|
.cache/
|
||||||
|
bin/
|
||||||
|
|
||||||
/docs_site/
|
*.mp4
|
||||||
|
|
||||||
*.dylib
|
*.dylib
|
||||||
*.DSYM
|
*.DSYM
|
||||||
*.d
|
*.d
|
||||||
|
*.pem
|
||||||
*.pyc
|
*.pyc
|
||||||
*.pyo
|
*.pyo
|
||||||
.*.swp
|
.*.swp
|
||||||
@@ -35,73 +36,62 @@ a.out
|
|||||||
*.class
|
*.class
|
||||||
*.pyxbldc
|
*.pyxbldc
|
||||||
*.vcd
|
*.vcd
|
||||||
*.qm
|
*.mo
|
||||||
*_pyx.cpp
|
*_pyx.cpp
|
||||||
|
*.stats
|
||||||
|
*.pkl
|
||||||
|
*.pkl*
|
||||||
config.json
|
config.json
|
||||||
clcache
|
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
compare_runtime*.html
|
compare_runtime*.html
|
||||||
|
selfdrive/modeld/models/tg_input_devices.json
|
||||||
|
|
||||||
persist
|
# build artifacts
|
||||||
|
docs_site/
|
||||||
selfdrive/pandad/pandad
|
selfdrive/pandad/pandad
|
||||||
cereal/services.h
|
cereal/services.h
|
||||||
cereal/gen
|
cereal/gen
|
||||||
cereal/messaging/bridge
|
cereal/messaging/bridge
|
||||||
selfdrive/logcatd/logcatd
|
|
||||||
selfdrive/mapd/default_speeds_by_region.json
|
|
||||||
system/proclogd/proclogd
|
|
||||||
selfdrive/ui/translations/alerts_generated.h
|
|
||||||
selfdrive/ui/translations/tmp
|
selfdrive/ui/translations/tmp
|
||||||
selfdrive/test/longitudinal_maneuvers/out
|
|
||||||
selfdrive/car/tests/cars_dump
|
selfdrive/car/tests/cars_dump
|
||||||
system/camerad/camerad
|
system/camerad/camerad
|
||||||
system/camerad/test/ae_gray_test
|
system/camerad/test/ae_gray_test
|
||||||
|
|
||||||
notebooks
|
|
||||||
hyperthneed
|
|
||||||
provisioning
|
|
||||||
|
|
||||||
.coverage*
|
.coverage*
|
||||||
coverage.xml
|
coverage.xml
|
||||||
htmlcov
|
htmlcov
|
||||||
pandaextra
|
|
||||||
|
|
||||||
.mypy_cache/
|
|
||||||
flycheck_*
|
|
||||||
|
|
||||||
cppcheck_report.txt
|
|
||||||
comma*.sh
|
|
||||||
|
|
||||||
selfdrive/modeld/thneed/compile
|
|
||||||
selfdrive/modeld/models/*.thneed
|
|
||||||
selfdrive/modeld/models/*.pkl
|
|
||||||
|
|
||||||
|
# openpilot log files
|
||||||
*.bz2
|
*.bz2
|
||||||
*.zst
|
*.zst
|
||||||
|
*.rlog
|
||||||
|
|
||||||
build/
|
build/
|
||||||
|
|
||||||
!**/.gitkeep
|
!**/.gitkeep
|
||||||
|
|
||||||
poetry.toml
|
|
||||||
Pipfile
|
|
||||||
|
|
||||||
### VisualStudioCode ###
|
### VisualStudioCode ###
|
||||||
|
*.vsix
|
||||||
|
.history
|
||||||
|
.ionide
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
.history/
|
||||||
!.vscode/settings.json
|
!.vscode/settings.json
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
!.vscode/*.code-snippets
|
!.vscode/*.code-snippets
|
||||||
|
|
||||||
# Local History for Visual Studio Code
|
# agents
|
||||||
.history/
|
.claude/
|
||||||
|
.context/
|
||||||
|
PLAN.md
|
||||||
|
TASK.md
|
||||||
|
CLAUDE.md
|
||||||
|
SKILL.md
|
||||||
|
|
||||||
# Built Visual Studio Code Extensions
|
### JetBrains ###
|
||||||
*.vsix
|
!.idea/customTargets.xml
|
||||||
|
!.idea/tools/*
|
||||||
### VisualStudioCode Patch ###
|
!.run/*
|
||||||
# Ignore all local history of files
|
|
||||||
.history
|
|
||||||
.ionide
|
|
||||||
.vs
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
3.12.13
|
||||||
Vendored
+43
-1
@@ -23,6 +23,11 @@
|
|||||||
"id": "args",
|
"id": "args",
|
||||||
"description": "Arguments to pass to the process",
|
"description": "Arguments to pass to the process",
|
||||||
"type": "promptString"
|
"type": "promptString"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "replayArg",
|
||||||
|
"type": "promptString",
|
||||||
|
"description": "Enter route or segment to replay."
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"configurations": [
|
"configurations": [
|
||||||
@@ -40,7 +45,44 @@
|
|||||||
"type": "cppdbg",
|
"type": "cppdbg",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/${input:cpp_process}",
|
"program": "${workspaceFolder}/${input:cpp_process}",
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Attach LLDB to Replay drive",
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "attach",
|
||||||
|
"pid": "${command:pickMyProcess}",
|
||||||
|
"sourceMap": {
|
||||||
|
".": "${workspaceFolder}/opendbc/safety"
|
||||||
|
},
|
||||||
|
"initCommands": [
|
||||||
|
"script import time; time.sleep(3)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Replay drive",
|
||||||
|
"type": "debugpy",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/opendbc/safety/tests/safety_replay/replay_drive.py",
|
||||||
|
"args": [
|
||||||
|
"${input:replayArg}"
|
||||||
|
],
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"justMyCode": false,
|
||||||
|
"env": {
|
||||||
|
"PYTHONPATH": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
"subProcess": true,
|
||||||
|
"stopOnEntry": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compounds": [
|
||||||
|
{
|
||||||
|
"name": "Replay drive + Safety LLDB",
|
||||||
|
"configurations": [
|
||||||
|
"Replay drive",
|
||||||
|
"Attach LLDB to Replay drive"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Vendored
-1
@@ -21,7 +21,6 @@
|
|||||||
"common/**",
|
"common/**",
|
||||||
"selfdrive/**",
|
"selfdrive/**",
|
||||||
"system/**",
|
"system/**",
|
||||||
"third_party/**",
|
|
||||||
"tools/**",
|
"tools/**",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+1291
File diff suppressed because it is too large
Load Diff
+30
-5
@@ -1,13 +1,38 @@
|
|||||||
FROM ghcr.io/commaai/openpilot-base:latest
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
ENV PYTHONUNBUFFERED=1
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
ENV OPENPILOT_PATH=/home/batman/openpilot
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
ENV PYTHONPATH=${OPENPILOT_PATH}:${PYTHONPATH}
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends sudo tzdata locales && \
|
||||||
|
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
|
||||||
|
ENV LANGUAGE=en_US:en
|
||||||
|
ENV LC_ALL=en_US.UTF-8
|
||||||
|
|
||||||
|
ENV NVIDIA_VISIBLE_DEVICES=all
|
||||||
|
ENV NVIDIA_DRIVER_CAPABILITIES=graphics,utility,compute
|
||||||
|
|
||||||
|
ARG USER=batman
|
||||||
|
ARG USER_UID=1001
|
||||||
|
RUN useradd -m -s /bin/bash -u $USER_UID $USER
|
||||||
|
RUN usermod -aG sudo $USER
|
||||||
|
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
|
||||||
|
USER $USER
|
||||||
|
|
||||||
|
ENV OPENPILOT_PATH=/home/$USER/openpilot
|
||||||
RUN mkdir -p ${OPENPILOT_PATH}
|
RUN mkdir -p ${OPENPILOT_PATH}
|
||||||
WORKDIR ${OPENPILOT_PATH}
|
WORKDIR ${OPENPILOT_PATH}
|
||||||
|
|
||||||
COPY . ${OPENPILOT_PATH}/
|
COPY --chown=$USER . ${OPENPILOT_PATH}/
|
||||||
|
|
||||||
RUN scons --cache-readonly -j$(nproc)
|
ENV UV_BIN="/home/$USER/.local/bin/"
|
||||||
|
ENV VIRTUAL_ENV=${OPENPILOT_PATH}/.venv
|
||||||
|
ENV PATH="$UV_BIN:$VIRTUAL_ENV/bin:$PATH"
|
||||||
|
RUN tools/setup_dependencies.sh && \
|
||||||
|
sudo rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
USER root
|
||||||
|
RUN git config --global --add safe.directory '*'
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
FROM ubuntu:24.04
|
|
||||||
|
|
||||||
ENV PYTHONUNBUFFERED=1
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y --no-install-recommends sudo tzdata locales ssh pulseaudio xvfb x11-xserver-utils gnome-screenshot python3-tk python3-dev && \
|
|
||||||
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
|
|
||||||
ENV LANGUAGE=en_US:en
|
|
||||||
ENV LC_ALL=en_US.UTF-8
|
|
||||||
|
|
||||||
COPY tools/install_ubuntu_dependencies.sh /tmp/tools/
|
|
||||||
RUN /tmp/tools/install_ubuntu_dependencies.sh && \
|
|
||||||
rm -rf /var/lib/apt/lists/* /tmp/* && \
|
|
||||||
cd /usr/lib/gcc/arm-none-eabi/* && \
|
|
||||||
rm -rf arm/ thumb/nofp thumb/v6* thumb/v8* thumb/v7+fp thumb/v7-r+fp.sp
|
|
||||||
|
|
||||||
# Add OpenCL
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
||||||
apt-utils \
|
|
||||||
alien \
|
|
||||||
unzip \
|
|
||||||
tar \
|
|
||||||
curl \
|
|
||||||
xz-utils \
|
|
||||||
dbus \
|
|
||||||
gcc-arm-none-eabi \
|
|
||||||
tmux \
|
|
||||||
vim \
|
|
||||||
libx11-6 \
|
|
||||||
wget \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
RUN mkdir -p /tmp/opencl-driver-intel && \
|
|
||||||
cd /tmp/opencl-driver-intel && \
|
|
||||||
wget https://github.com/intel/llvm/releases/download/2024-WW14/oclcpuexp-2024.17.3.0.09_rel.tar.gz && \
|
|
||||||
wget https://github.com/oneapi-src/oneTBB/releases/download/v2021.12.0/oneapi-tbb-2021.12.0-lin.tgz && \
|
|
||||||
mkdir -p /opt/intel/oclcpuexp_2024.17.3.0.09_rel && \
|
|
||||||
cd /opt/intel/oclcpuexp_2024.17.3.0.09_rel && \
|
|
||||||
tar -zxvf /tmp/opencl-driver-intel/oclcpuexp-2024.17.3.0.09_rel.tar.gz && \
|
|
||||||
mkdir -p /etc/OpenCL/vendors && \
|
|
||||||
echo /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64/libintelocl.so > /etc/OpenCL/vendors/intel_expcpu.icd && \
|
|
||||||
cd /opt/intel && \
|
|
||||||
tar -zxvf /tmp/opencl-driver-intel/oneapi-tbb-2021.12.0-lin.tgz && \
|
|
||||||
ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbb.so /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \
|
|
||||||
ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbbmalloc.so /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \
|
|
||||||
ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbb.so.12 /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \
|
|
||||||
ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbbmalloc.so.2 /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \
|
|
||||||
mkdir -p /etc/ld.so.conf.d && \
|
|
||||||
echo /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 > /etc/ld.so.conf.d/libintelopenclexp.conf && \
|
|
||||||
ldconfig -f /etc/ld.so.conf.d/libintelopenclexp.conf && \
|
|
||||||
cd / && \
|
|
||||||
rm -rf /tmp/opencl-driver-intel
|
|
||||||
|
|
||||||
ENV NVIDIA_VISIBLE_DEVICES=all
|
|
||||||
ENV NVIDIA_DRIVER_CAPABILITIES=graphics,utility,compute
|
|
||||||
ENV QTWEBENGINE_DISABLE_SANDBOX=1
|
|
||||||
|
|
||||||
RUN dbus-uuidgen > /etc/machine-id
|
|
||||||
|
|
||||||
ARG USER=batman
|
|
||||||
ARG USER_UID=1001
|
|
||||||
RUN useradd -m -s /bin/bash -u $USER_UID $USER
|
|
||||||
RUN usermod -aG sudo $USER
|
|
||||||
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
|
|
||||||
USER $USER
|
|
||||||
|
|
||||||
COPY --chown=$USER pyproject.toml uv.lock /home/$USER
|
|
||||||
COPY --chown=$USER tools/install_python_dependencies.sh /home/$USER/tools/
|
|
||||||
|
|
||||||
ENV VIRTUAL_ENV=/home/$USER/.venv
|
|
||||||
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
|
|
||||||
RUN cd /home/$USER && \
|
|
||||||
tools/install_python_dependencies.sh && \
|
|
||||||
rm -rf tools/ pyproject.toml uv.lock .cache
|
|
||||||
|
|
||||||
USER root
|
|
||||||
RUN sudo git config --global --add safe.directory /tmp/openpilot
|
|
||||||
Vendored
+17
-39
@@ -22,7 +22,7 @@ shopt -s huponexit # kill all child processes when the shell exits
|
|||||||
|
|
||||||
export CI=1
|
export CI=1
|
||||||
export PYTHONWARNINGS=error
|
export PYTHONWARNINGS=error
|
||||||
export LOGPRINT=debug
|
#export LOGPRINT=debug # this has gotten too spammy...
|
||||||
export TEST_DIR=${env.TEST_DIR}
|
export TEST_DIR=${env.TEST_DIR}
|
||||||
export SOURCE_DIR=${env.SOURCE_DIR}
|
export SOURCE_DIR=${env.SOURCE_DIR}
|
||||||
export GIT_BRANCH=${env.GIT_BRANCH}
|
export GIT_BRANCH=${env.GIT_BRANCH}
|
||||||
@@ -166,8 +166,8 @@ node {
|
|||||||
env.GIT_BRANCH = checkout(scm).GIT_BRANCH
|
env.GIT_BRANCH = checkout(scm).GIT_BRANCH
|
||||||
env.GIT_COMMIT = checkout(scm).GIT_COMMIT
|
env.GIT_COMMIT = checkout(scm).GIT_COMMIT
|
||||||
|
|
||||||
def excludeBranches = ['__nightly', 'devel', 'devel-staging', 'release3', 'release3-staging',
|
def excludeBranches = ['__nightly', 'devel', 'devel-staging',
|
||||||
'testing-closet*', 'hotfix-*']
|
'release-tizi', 'release-tizi-staging', 'release-mici', 'release-mici-staging', 'testing-closet*', 'hotfix-*']
|
||||||
def excludeRegex = excludeBranches.join('|').replaceAll('\\*', '.*')
|
def excludeRegex = excludeBranches.join('|').replaceAll('\\*', '.*')
|
||||||
|
|
||||||
if (env.BRANCH_NAME != 'master' && !env.BRANCH_NAME.contains('__jenkins_loop_')) {
|
if (env.BRANCH_NAME != 'master' && !env.BRANCH_NAME.contains('__jenkins_loop_')) {
|
||||||
@@ -178,20 +178,20 @@ node {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (env.BRANCH_NAME == 'devel-staging') {
|
if (env.BRANCH_NAME == 'devel-staging') {
|
||||||
deviceStage("build release3-staging", "tici-needs-can", [], [
|
deviceStage("build release-tizi-staging", "tizi-needs-can", [], [
|
||||||
step("build release3-staging", "RELEASE_BRANCH=release3-staging $SOURCE_DIR/release/build_release.sh"),
|
step("build release-tizi-staging", "RELEASE_BRANCH=release-tizi-staging,release-mici-staging $SOURCE_DIR/release/build_release.sh"),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env.BRANCH_NAME == '__nightly') {
|
if (env.BRANCH_NAME == '__nightly') {
|
||||||
parallel (
|
parallel (
|
||||||
'nightly': {
|
'nightly': {
|
||||||
deviceStage("build nightly", "tici-needs-can", [], [
|
deviceStage("build nightly", "tizi-needs-can", [], [
|
||||||
step("build nightly", "RELEASE_BRANCH=nightly $SOURCE_DIR/release/build_release.sh"),
|
step("build nightly", "RELEASE_BRANCH=nightly $SOURCE_DIR/release/build_release.sh"),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
'nightly-dev': {
|
'nightly-dev': {
|
||||||
deviceStage("build nightly-dev", "tici-needs-can", [], [
|
deviceStage("build nightly-dev", "tizi-needs-can", [], [
|
||||||
step("build nightly-dev", "PANDA_DEBUG_BUILD=1 RELEASE_BRANCH=nightly-dev $SOURCE_DIR/release/build_release.sh"),
|
step("build nightly-dev", "PANDA_DEBUG_BUILD=1 RELEASE_BRANCH=nightly-dev $SOURCE_DIR/release/build_release.sh"),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
@@ -200,63 +200,43 @@ node {
|
|||||||
|
|
||||||
if (!env.BRANCH_NAME.matches(excludeRegex)) {
|
if (!env.BRANCH_NAME.matches(excludeRegex)) {
|
||||||
parallel (
|
parallel (
|
||||||
// tici tests
|
|
||||||
'onroad tests': {
|
'onroad tests': {
|
||||||
deviceStage("onroad", "tici-needs-can", ["UNSAFE=1"], [
|
deviceStage("onroad", "tizi-needs-can", ["UNSAFE=1"], [
|
||||||
step("build openpilot", "cd system/manager && ./build.py"),
|
step("build openpilot", "cd system/manager && ./build.py"),
|
||||||
step("check dirty", "release/check-dirty.sh"),
|
step("check dirty", "release/check-dirty.sh"),
|
||||||
step("onroad tests", "pytest selfdrive/test/test_onroad.py -s", [timeout: 60]),
|
step("onroad tests", "pytest selfdrive/test/test_onroad.py -s", [timeout: 60]),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
'HW + Unit Tests': {
|
'HW + Unit Tests': {
|
||||||
deviceStage("tici-hardware", "tici-common", ["UNSAFE=1"], [
|
deviceStage("tizi-hardware", "tizi-common", ["UNSAFE=1"], [
|
||||||
step("build", "cd system/manager && ./build.py"),
|
step("build", "cd system/manager && ./build.py"),
|
||||||
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]),
|
|
||||||
step("test power draw", "pytest -s system/hardware/tici/tests/test_power_draw.py"),
|
step("test power draw", "pytest -s system/hardware/tici/tests/test_power_draw.py"),
|
||||||
step("test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py", [diffPaths: ["system/loggerd/"]]),
|
step("test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py", [diffPaths: ["system/loggerd/"]]),
|
||||||
step("test pigeond", "pytest system/ubloxd/tests/test_pigeond.py", [diffPaths: ["system/ubloxd/"]]),
|
|
||||||
step("test manager", "pytest system/manager/test/test_manager.py"),
|
step("test manager", "pytest system/manager/test/test_manager.py"),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
'loopback': {
|
|
||||||
deviceStage("loopback", "tici-loopback", ["UNSAFE=1"], [
|
|
||||||
step("build openpilot", "cd system/manager && ./build.py"),
|
|
||||||
step("test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"),
|
|
||||||
])
|
|
||||||
},
|
|
||||||
'camerad AR0231': {
|
|
||||||
deviceStage("AR0231", "tici-ar0231", ["UNSAFE=1"], [
|
|
||||||
step("build", "cd system/manager && ./build.py"),
|
|
||||||
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 60]),
|
|
||||||
step("test exposure", "pytest system/camerad/test/test_exposure.py"),
|
|
||||||
])
|
|
||||||
},
|
|
||||||
'camerad OX03C10': {
|
'camerad OX03C10': {
|
||||||
deviceStage("OX03C10", "tici-ox03c10", ["UNSAFE=1"], [
|
deviceStage("OX03C10", "tizi-ox03c10", ["UNSAFE=1"], [
|
||||||
step("build", "cd system/manager && ./build.py"),
|
step("build", "cd system/manager && ./build.py"),
|
||||||
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 60]),
|
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py"),
|
||||||
step("test exposure", "pytest system/camerad/test/test_exposure.py"),
|
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 90]),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
'camerad OS04C10': {
|
'camerad OS04C10': {
|
||||||
deviceStage("OS04C10", "tici-os04c10", ["UNSAFE=1"], [
|
deviceStage("OS04C10", "tici-os04c10", ["UNSAFE=1"], [
|
||||||
step("build", "cd system/manager && ./build.py"),
|
step("build", "cd system/manager && ./build.py"),
|
||||||
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 60]),
|
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py"),
|
||||||
step("test exposure", "pytest system/camerad/test/test_exposure.py"),
|
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 90]),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
'sensord': {
|
'sensord': {
|
||||||
deviceStage("LSM + MMC", "tici-lsmc", ["UNSAFE=1"], [
|
deviceStage("LSM + MMC", "tizi-lsmc", ["UNSAFE=1"], [
|
||||||
step("build", "cd system/manager && ./build.py"),
|
|
||||||
step("test sensord", "pytest system/sensord/tests/test_sensord.py"),
|
|
||||||
])
|
|
||||||
deviceStage("BMX + LSM", "tici-bmx-lsm", ["UNSAFE=1"], [
|
|
||||||
step("build", "cd system/manager && ./build.py"),
|
step("build", "cd system/manager && ./build.py"),
|
||||||
step("test sensord", "pytest system/sensord/tests/test_sensord.py"),
|
step("test sensord", "pytest system/sensord/tests/test_sensord.py"),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
'replay': {
|
'replay': {
|
||||||
deviceStage("model-replay", "tici-replay", ["UNSAFE=1"], [
|
deviceStage("model-replay", "tizi-replay", ["UNSAFE=1"], [
|
||||||
step("build", "cd system/manager && ./build.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]),
|
step("build", "cd system/manager && ./build.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]),
|
||||||
step("model replay", "selfdrive/test/process_replay/model_replay.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]),
|
step("model replay", "selfdrive/test/process_replay/model_replay.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]),
|
||||||
])
|
])
|
||||||
@@ -264,11 +244,9 @@ node {
|
|||||||
'tizi': {
|
'tizi': {
|
||||||
deviceStage("tizi", "tizi", ["UNSAFE=1"], [
|
deviceStage("tizi", "tizi", ["UNSAFE=1"], [
|
||||||
step("build openpilot", "cd system/manager && ./build.py"),
|
step("build openpilot", "cd system/manager && ./build.py"),
|
||||||
step("test pandad loopback", "SINGLE_PANDA=1 pytest selfdrive/pandad/tests/test_pandad_loopback.py"),
|
step("test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"),
|
||||||
step("test pandad spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"),
|
step("test pandad spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"),
|
||||||
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]),
|
|
||||||
step("test amp", "pytest system/hardware/tici/tests/test_amplifier.py"),
|
step("test amp", "pytest system/hardware/tici/tests/test_amplifier.py"),
|
||||||
step("test qcomgpsd", "pytest system/qcomgpsd/tests/test_qcomgpsd.py", [diffPaths: ["system/qcomgpsd/"]]),
|
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
# Custom MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024, Haibin Wen, SUNNYPILOT LLC
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to view and modify the Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1. **Permission Required**: Permission Required for Commercial, For-Profit, or Closed Source Use: Use of the Software, in whole or in part, for any commercial purposes, for-profit projects, or in closed source projects requires explicit written permission from the original author(s).
|
||||||
|
|
||||||
|
2. **Redistribution**: Any redistribution of the Software, modified or unmodified, must retain this license notice and the following acknowledgment:
|
||||||
|
"This software is licensed under a custom license requiring permission for use."
|
||||||
|
|
||||||
|
3. **Visibility**: Any project that uses the Software must visibly mention the following acknowledgment:
|
||||||
|
"This project uses software from Haibin Wen and SUNNYPILOT LLC and is licensed under a custom license requiring permission for use."
|
||||||
|
|
||||||
|
4. **No Warranty**: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Contact sunnypilot Support <support@sunnypilot.ai> for permission requests.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Haibin Wen, SUNNYPILOT LLC
|
||||||
@@ -1,143 +1,76 @@
|
|||||||
## ⚠️ 법적 안내 / Legal Notice
|
## ✍ To install this fork use installer.comma.ai/infiniteCable2/master (Comma Four compatible)
|
||||||
|
|
||||||
🚫 대한민국 자동차관리법 개정안에 따라, 본 소프트웨어를 실제 차량에 장착하거나 주행에 사용하는 것은 법률에 위배될 수 있습니다.
|

|
||||||
이 저장소에 있는 모든 소프트웨어는 **연구, 실험, 시뮬레이션 목적**으로만 제공됩니다.
|
|
||||||
개발자는 본 소프트웨어의 실제 사용으로 인해 발생하는 **모든 법적 책임을 지지 않습니다.**
|
|
||||||
|
|
||||||
In accordance with the amended **Korean Motor Vehicle Management Act** (effective August 14, 2025),
|
## 🌞 What is sunnypilot?
|
||||||
**modifying or installing software that affects the safe operation of a vehicle** is prohibited.
|
[sunnypilot](https://github.com/sunnyhaibin/sunnypilot) is a fork of comma.ai's openpilot, an open source driver assistance system. sunnypilot offers the user a unique driving experience for over 300+ supported car makes and models with modified behaviors of driving assist engagements. sunnypilot complies with comma.ai's safety rules as accurately as possible.
|
||||||
|
|
||||||
This software is provided **for research and educational use only**.
|
## 💭 Join our Community Forum
|
||||||
The developer does **not take any responsibility** for real-world installation or usage.
|
Join the official sunnypilot community forum to stay up to date with all the latest features and be a part of shaping the future of sunnypilot!
|
||||||
|
* https://community.sunnypilot.ai/
|
||||||
|
|
||||||
**Carrotpilot에서 사용하는 차량(현대,기아)에 따라 Harness가 다릅니다..**
|
## Documentation
|
||||||
- CAN통신차량: Comma 정품 Harness, Camera에 연결
|
https://docs.sunnypilot.ai/ is your one stop shop for everything from features to installation to FAQ about the sunnypilot
|
||||||
- CANFD-일반차량: Comma정품 Harness, Camera에 연결
|
|
||||||
- CANFD-HDA2(ADAS Module 장착)차량: 사제 Harness, ADAS Module에 연결
|
## 🚘 Running on a dedicated device in a car
|
||||||
- 모든차량이 지원되는것이 아니니 반드시 확인바랍니다.
|
First, check out this list of items you'll need to [get started](https://community.sunnypilot.ai/t/getting-started-using-sunnypilot-in-your-supported-car/251).
|
||||||
|
|
||||||
**In CarrotPilot, the harness used varies depending on the vehicle(HKG):**
|
## Installation
|
||||||
* **CAN vehicles** Use the official Comma harness, connected to the camera.
|
Next, refer to the sunnypilot community forum for [installation instructions](https://community.sunnypilot.ai/t/read-before-installing-sunnypilot/254), as well as a complete list of [Recommended Branch Installations](https://community.sunnypilot.ai/t/recommended-branch-installations/235).
|
||||||
* **CAN FD (standard) vehicles** Use the official Comma harness, connected to the camera.
|
|
||||||
* **CAN FD vehicles with HDA2 (ADAS module equipped)** Use an aftermarket harness, connected to the ADAS module.
|
## 🎆 Pull Requests
|
||||||
* Please note that not all vehicles are supported.
|
We welcome both pull requests and issues on GitHub. Bug fixes are encouraged.
|
||||||
|
|
||||||
|
Pull requests should be against the most current `master` branch.
|
||||||
|
|
||||||
|
## 📊 User Data
|
||||||
|
|
||||||
|
By default, sunnypilot uploads the driving data to comma servers. You can also access your data through [comma connect](https://connect.comma.ai/).
|
||||||
|
|
||||||
|
sunnypilot is open source software. The user is free to disable data collection if they wish to do so.
|
||||||
|
|
||||||
|
sunnypilot logs the road-facing camera, CAN, GPS, IMU, magnetometer, thermal sensors, crashes, and operating system logs.
|
||||||
|
The driver-facing camera and microphone are only logged if you explicitly opt-in in settings.
|
||||||
|
|
||||||
|
By using this software, you understand that use of this software or its related services will generate certain types of user data, which may be logged and stored at the sole discretion of comma. By accepting this agreement, you grant an irrevocable, perpetual, worldwide right to comma for the use of this data.
|
||||||
|
|
||||||
|
## Licensing
|
||||||
|
|
||||||
|
sunnypilot is released under the [MIT License](LICENSE). This repository includes original work as well as significant portions of code derived from [openpilot by comma.ai](https://github.com/commaai/openpilot), which is also released under the MIT license with additional disclaimers.
|
||||||
|
|
||||||
|
The original openpilot license notice, including comma.ai’s indemnification and alpha software disclaimer, is reproduced below as required:
|
||||||
|
|
||||||
|
> openpilot is released under the MIT license. Some parts of the software are released under other licenses as specified.
|
||||||
|
>
|
||||||
|
> Any user of this software shall indemnify and hold harmless Comma.ai, Inc. and its directors, officers, employees, agents, stockholders, affiliates, subcontractors and customers from and against all allegations, claims, actions, suits, demands, damages, liabilities, obligations, losses, settlements, judgments, costs and expenses (including without limitation attorneys’ fees and costs) which arise out of, relate to or result from any use of this software by user.
|
||||||
|
>
|
||||||
|
> **THIS IS ALPHA QUALITY SOFTWARE FOR RESEARCH PURPOSES ONLY. THIS IS NOT A PRODUCT.
|
||||||
|
> YOU ARE RESPONSIBLE FOR COMPLYING WITH LOCAL LAWS AND REGULATIONS.
|
||||||
|
> NO WARRANTY EXPRESSED OR IMPLIED.**
|
||||||
|
|
||||||
|
For full license terms, please see the [`LICENSE`](LICENSE) file.
|
||||||
|
|
||||||
|
## 💰 Support sunnypilot
|
||||||
|
If you find any of the features useful, consider becoming a [sponsor on GitHub](https://github.com/sponsors/sunnyhaibin) to support future feature development and improvements.
|
||||||
|
|
||||||
|
|
||||||
<div align="center" style="text-align: center;">
|
By becoming a sponsor, you will gain access to exclusive content, early access to new features, and the opportunity to directly influence the project's development.
|
||||||
|
|
||||||
<h1>carrotpilot</h1>
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
<a href="https://g4iwnl.gitbook.io/carrotpilot">Manual</a>
|
|
||||||
</h3>
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
<div align="center" style="text-align: center;">
|
<h3>GitHub Sponsor</h3>
|
||||||
|
|
||||||
<h1>openpilot</h1>
|
<a href="https://github.com/sponsors/sunnyhaibin">
|
||||||
|
<img src="https://user-images.githubusercontent.com/47793918/244135584-9800acbd-69fd-4b2b-bec9-e5fa2d85c817.png" alt="Become a Sponsor" width="300" style="max-width: 100%; height: auto;">
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
|
||||||
<p>
|
<h3>PayPal</h3>
|
||||||
<b>openpilot is an operating system for robotics.</b>
|
|
||||||
<br>
|
|
||||||
Currently, it upgrades the driver assistance system in 275+ supported cars.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>
|
<a href="https://paypal.me/sunnyhaibin0850" target="_blank">
|
||||||
<a href="https://docs.comma.ai">Docs</a>
|
<img src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" alt="PayPal this" title="PayPal - The safer, easier way to pay online!" border="0" />
|
||||||
<span> · </span>
|
</a>
|
||||||
<a href="https://docs.comma.ai/contributing/roadmap/">Roadmap</a>
|
<br></br>
|
||||||
<span> · </span>
|
|
||||||
<a href="https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md">Contribute</a>
|
|
||||||
<span> · </span>
|
|
||||||
<a href="https://discord.comma.ai">Community</a>
|
|
||||||
<span> · </span>
|
|
||||||
<a href="https://comma.ai/shop">Try it on a comma 3X</a>
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
Quick start: `bash <(curl -fsSL openpilot.comma.ai)`
|
Your continuous love and support are greatly appreciated! Enjoy 🥰
|
||||||
|
|
||||||

|
<span>-</span> Jason, Founder of sunnypilot
|
||||||
[](https://codecov.io/gh/commaai/openpilot)
|
|
||||||
[](LICENSE)
|
|
||||||
[](https://x.com/comma_ai)
|
|
||||||
[](https://discord.comma.ai)
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><a href="https://youtu.be/NmBfgOanCyk" title="Video By Greer Viau"><img src="https://github.com/commaai/openpilot/assets/8762862/2f7112ae-f748-4f39-b617-fabd689c3772"></a></td>
|
|
||||||
<td><a href="https://youtu.be/VHKyqZ7t8Gw" title="Video By Logan LeGrand"><img src="https://github.com/commaai/openpilot/assets/8762862/92351544-2833-40d7-9e0b-7ef7ae37ec4c"></a></td>
|
|
||||||
<td><a href="https://youtu.be/SUIZYzxtMQs" title="A drive to Taco Bell"><img src="https://github.com/commaai/openpilot/assets/8762862/05ceefc5-2628-439c-a9b2-89ce77dc6f63"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
Using openpilot in a car
|
|
||||||
------
|
|
||||||
|
|
||||||
To use openpilot in a car, you need four things:
|
|
||||||
1. **Supported Device:** a comma 3/3X, available at [comma.ai/shop](https://comma.ai/shop/comma-3x).
|
|
||||||
2. **Software:** The setup procedure for the comma 3/3X allows users to enter a URL for custom software. Use the URL `openpilot.comma.ai` to install the release version.
|
|
||||||
3. **Supported Car:** Ensure that you have one of [the 275+ supported cars](docs/CARS.md).
|
|
||||||
4. **Car Harness:** You will also need a [car harness](https://comma.ai/shop/car-harness) to connect your comma 3/3X to your car.
|
|
||||||
|
|
||||||
We have detailed instructions for [how to install the harness and device in a car](https://comma.ai/setup). Note that it's possible to run openpilot on [other hardware](https://blog.comma.ai/self-driving-car-for-free/), although it's not plug-and-play.
|
|
||||||
|
|
||||||
### Branches
|
|
||||||
| branch | URL | description |
|
|
||||||
|------------------|----------------------------------------|-------------------------------------------------------------------------------------|
|
|
||||||
| `release3` | openpilot.comma.ai | This is openpilot's release branch. |
|
|
||||||
| `release3-staging` | openpilot-test.comma.ai | This is the staging branch for releases. Use it to get new releases slightly early. |
|
|
||||||
| `nightly` | openpilot-nightly.comma.ai | This is the bleeding edge development branch. Do not expect this to be stable. |
|
|
||||||
| `nightly-dev` | installer.comma.ai/commaai/nightly-dev | Same as nightly, but includes experimental development features for some cars. |
|
|
||||||
|
|
||||||
To start developing openpilot
|
|
||||||
------
|
|
||||||
|
|
||||||
openpilot is developed by [comma](https://comma.ai/) and by users like you. We welcome both pull requests and issues on [GitHub](http://github.com/commaai/openpilot).
|
|
||||||
|
|
||||||
* Join the [community Discord](https://discord.comma.ai)
|
|
||||||
* Check out [the contributing docs](docs/CONTRIBUTING.md)
|
|
||||||
* Check out the [openpilot tools](tools/)
|
|
||||||
* Read about the [development workflow](docs/WORKFLOW.md)
|
|
||||||
* Code documentation lives at https://docs.comma.ai
|
|
||||||
* Information about running openpilot lives on the [community wiki](https://github.com/commaai/openpilot/wiki)
|
|
||||||
|
|
||||||
Want to get paid to work on openpilot? [comma is hiring](https://comma.ai/jobs#open-positions) and offers lots of [bounties](https://comma.ai/bounties) for external contributors.
|
|
||||||
|
|
||||||
Safety and Testing
|
|
||||||
----
|
|
||||||
|
|
||||||
* openpilot observes [ISO26262](https://en.wikipedia.org/wiki/ISO_26262) guidelines, see [SAFETY.md](docs/SAFETY.md) for more details.
|
|
||||||
* openpilot has software-in-the-loop [tests](.github/workflows/selfdrive_tests.yaml) that run on every commit.
|
|
||||||
* The code enforcing the safety model lives in panda and is written in C, see [code rigor](https://github.com/commaai/panda#code-rigor) for more details.
|
|
||||||
* panda has software-in-the-loop [safety tests](https://github.com/commaai/panda/tree/master/tests/safety).
|
|
||||||
* Internally, we have a hardware-in-the-loop Jenkins test suite that builds and unit tests the various processes.
|
|
||||||
* panda has additional hardware-in-the-loop [tests](https://github.com/commaai/panda/blob/master/Jenkinsfile).
|
|
||||||
* We run the latest openpilot in a testing closet containing 10 comma devices continuously replaying routes.
|
|
||||||
|
|
||||||
Licensing
|
|
||||||
------
|
|
||||||
|
|
||||||
openpilot is released under the MIT license. Some parts of the software are released under other licenses as specified.
|
|
||||||
|
|
||||||
Any user of this software shall indemnify and hold harmless Comma.ai, Inc. and its directors, officers, employees, agents, stockholders, affiliates, subcontractors and customers from and against all allegations, claims, actions, suits, demands, damages, liabilities, obligations, losses, settlements, judgments, costs and expenses (including without limitation attorneys’ fees and costs) which arise out of, relate to or result from any use of this software by user.
|
|
||||||
|
|
||||||
**THIS IS ALPHA QUALITY SOFTWARE FOR RESEARCH PURPOSES ONLY. THIS IS NOT A PRODUCT.
|
|
||||||
YOU ARE RESPONSIBLE FOR COMPLYING WITH LOCAL LAWS AND REGULATIONS.
|
|
||||||
NO WARRANTY EXPRESSED OR IMPLIED.**
|
|
||||||
|
|
||||||
User Data and comma Account
|
|
||||||
------
|
|
||||||
|
|
||||||
By default, openpilot uploads the driving data to our servers. You can also access your data through [comma connect](https://connect.comma.ai/). We use your data to train better models and improve openpilot for everyone.
|
|
||||||
|
|
||||||
openpilot is open source software: the user is free to disable data collection if they wish to do so.
|
|
||||||
|
|
||||||
openpilot logs the road-facing cameras, CAN, GPS, IMU, magnetometer, thermal sensors, crashes, and operating system logs.
|
|
||||||
The driver-facing camera is only logged if you explicitly opt-in in settings. The microphone is not recorded.
|
|
||||||
|
|
||||||
By using openpilot, you agree to [our Privacy Policy](https://comma.ai/privacy). You understand that use of this software or its related services will generate certain types of user data, which may be logged and stored at the sole discretion of comma. By accepting this agreement, you grant an irrevocable, perpetual, worldwide right to comma for the use of this data.
|
|
||||||
|
|||||||
+59
-77
@@ -1,95 +1,77 @@
|
|||||||
Carrot2-v9 (2026-02-xx)
|
Version 0.11.2 (2026-06-15)
|
||||||
========================
|
========================
|
||||||
* CD210 model
|
|
||||||
* web carrot_man (http://ip:7000)
|
|
||||||
* fix speed based TF
|
|
||||||
|
|
||||||
Carrot2-v9 (2026-01-xx)
|
|
||||||
|
Version 0.11.1 (2026-05-18)
|
||||||
========================
|
========================
|
||||||
* WMI model
|
* New driver monitoring model
|
||||||
* Activate corner radar(HDA2)
|
* Improved image processing pipeline for driver camera
|
||||||
* fix Angle Steering(HKG car)
|
* Improved thermal policy for comma four
|
||||||
* Keep blinker while LaneChange
|
* Acura MDX 2022-24 support thanks to mvl-boston!
|
||||||
* Speed based TF adjustment
|
* Rivian R1S and R1T 2025 support thanks to lukasloetkolben!
|
||||||
* Sorento HEV 4WD(Niro HEV), Long bug fix.
|
|
||||||
|
|
||||||
Carrot2-v9 (2025-12-06)
|
Version 0.11.0 (2026-03-17)
|
||||||
========================
|
========================
|
||||||
* DarkSouls model
|
* New driving model #36798
|
||||||
* fix Angle Steering(HKG car)
|
* Fully trained using a learned simulator
|
||||||
* fix LaneChange desire
|
* Improved longitudinal performance in Experimental mode
|
||||||
|
* Reduce comma four standby power usage by 77% to 52 mW
|
||||||
|
* Kia K7 2017 support thanks to royjr!
|
||||||
|
* Lexus LS 2018 support thanks to Hacheoy!
|
||||||
|
|
||||||
Carrot2-v9 (2025-12-06)
|
Version 0.10.3 (2025-12-17)
|
||||||
========================
|
========================
|
||||||
* PP(planplus) model
|
* New driving model #36249
|
||||||
* fixDM
|
* New temporal policy architecture
|
||||||
* fix angle steering torque(HKG car)
|
* New on-policy training physics noise model
|
||||||
|
* New driver monitoring model #36409
|
||||||
|
* Trained on a new dataset, including comma four data
|
||||||
|
* Improved inter-process communication memory efficiency
|
||||||
|
|
||||||
Carrot2-v9 (2025-12-03)
|
Version 0.10.2 (2025-11-19)
|
||||||
========================
|
========================
|
||||||
* ST model
|
* comma four support
|
||||||
* fix CasperEV FCA11
|
|
||||||
* fix DriverMonitoring alert (for USA)
|
|
||||||
* apply livePose
|
|
||||||
* update sensor code
|
|
||||||
|
|
||||||
Carrot2-v9 (2025-10-17)
|
Version 0.10.1 (2025-09-08)
|
||||||
========================
|
========================
|
||||||
* Nuggets In Dijon model
|
* New driving model #36276
|
||||||
* Setting: Adjust traffic stop distance
|
* World Model: removed global localization inputs
|
||||||
* liveLocationKalman -> livePose
|
* World Model: 2x the number of parameters
|
||||||
* C3x lite
|
* World Model: trained on 4x the number of segments
|
||||||
|
* VAE Compression Model: new architecture and training objective
|
||||||
|
* Driving Vision Model: trained on 4x the number of segments
|
||||||
|
* New Driver Monitoring model #36198
|
||||||
|
* Acura TLX 2021 support thanks to MVL!
|
||||||
|
* Honda City 2023 support thanks to vanillagorillaa and drFritz!
|
||||||
|
* Honda N-Box 2018 support thanks to miettal!
|
||||||
|
* Honda Odyssey 2021-25 support thanks to csouers and MVL!
|
||||||
|
* Honda Passport 2026 support thanks to vanillagorillaa and MVL!
|
||||||
|
|
||||||
Carrot2-v9 (2025-09-21)
|
Version 0.10.0 (2025-08-05)
|
||||||
========================
|
|
||||||
* GWM Model
|
|
||||||
* Lead + 1 detect (전전차 감지기능)
|
|
||||||
* Improve radar vision matching
|
|
||||||
* Auto safe-mode on stopped vehicle detection
|
|
||||||
|
|
||||||
Carrot2-v9 (2025-09-xx)
|
|
||||||
========================
|
|
||||||
* TR16 Model
|
|
||||||
* RadarTrack Option:3 (Cutin Detect, vision fail detection)
|
|
||||||
* RdarTrack Option: 2 (always use SCC radar)
|
|
||||||
* Brake light (CANFD)
|
|
||||||
|
|
||||||
|
|
||||||
Carrot2-v9 (2025-08-12)
|
|
||||||
========================
|
|
||||||
* TombRaider16 v2 model.
|
|
||||||
* Remove ShowPathMode CruiseOff
|
|
||||||
* Add CancelButtonMode (0: Long Only, 1: Long + Lat)
|
|
||||||
* fix CASPER cruise button
|
|
||||||
* bugfix. Mapbox ATC with Waze
|
|
||||||
* ScreenRecorder 3 -> 20min
|
|
||||||
* fix RadarTrack processing
|
|
||||||
|
|
||||||
Carrot2-v9 (2025-08-04)
|
|
||||||
========================
|
|
||||||
* CruiseSpeedUnit
|
|
||||||
* fix RadarTrack processing
|
|
||||||
|
|
||||||
Carrot2-v9 (2025-08-03)
|
|
||||||
========================
|
|
||||||
* IONIQ9 support
|
|
||||||
* fix StockSCC bug.
|
|
||||||
* fix CPU usage(card: core 4->6)
|
|
||||||
|
|
||||||
Carrot2-v9 (2025-08-01)
|
|
||||||
========================
|
|
||||||
* SpaceLab V3 model
|
|
||||||
* RadarTracks support(CANFD)
|
|
||||||
* new CanParser
|
|
||||||
|
|
||||||
|
|
||||||
Version 0.9.9 (2025-04-30)
|
|
||||||
========================
|
========================
|
||||||
* New driving model
|
* New driving model
|
||||||
|
* New training architecture
|
||||||
|
* Described in our CVPR paper: "Learning to Drive from a World Model"
|
||||||
|
* Longitudinal MPC replaced by E2E planning from World Model in Experimental Mode
|
||||||
|
* Action from lateral MPC as training objective replaced by E2E planning from World Model
|
||||||
|
* Low-speed lead car ground-truth fixes
|
||||||
|
* Enable live-learned steering actuation delay
|
||||||
|
* Opt-in audio recording for dashcam video
|
||||||
|
* Acura MDX 2025 support thanks to vanillagorillaa and MVL!
|
||||||
|
* Honda Accord 2023-25 support thanks to vanillagorillaa and MVL!
|
||||||
|
* Honda CR-V 2023-25 support thanks to vanillagorillaa and MVL!
|
||||||
|
* Honda Pilot 2023-25 support thanks to vanillagorillaa and MVL!
|
||||||
|
|
||||||
|
Version 0.9.9 (2025-05-23)
|
||||||
|
========================
|
||||||
|
* New driving model
|
||||||
|
* New training architecture using parts from MLSIM
|
||||||
|
* Steering actuation delay is now learned online
|
||||||
|
* Ford Escape 2023-24 support thanks to incognitojam!
|
||||||
|
* Ford Kuga 2024 support thanks to incognitojam!
|
||||||
|
* Hyundai Nexo 2021 support thanks to sunnyhaibin!
|
||||||
* Tesla Model 3 and Y support thanks to lukasloetkolben!
|
* Tesla Model 3 and Y support thanks to lukasloetkolben!
|
||||||
* Coming soon
|
* Lexus RC 2023 support thanks to nelsonjchen!
|
||||||
* New driving model supervised by MLSIM
|
|
||||||
* An online learner for steering actuator delay
|
|
||||||
|
|
||||||
Version 0.9.8 (2025-02-28)
|
Version 0.9.8 (2025-02-28)
|
||||||
========================
|
========================
|
||||||
|
|||||||
+192
-272
@@ -4,327 +4,211 @@ import sys
|
|||||||
import sysconfig
|
import sysconfig
|
||||||
import platform
|
import platform
|
||||||
import shlex
|
import shlex
|
||||||
|
import importlib
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import SCons.Errors
|
import SCons.Errors
|
||||||
|
from SCons.Defaults import _stripixes
|
||||||
|
|
||||||
|
TICI = os.path.isfile('/TICI')
|
||||||
|
|
||||||
SCons.Warnings.warningAsException(True)
|
SCons.Warnings.warningAsException(True)
|
||||||
|
|
||||||
TICI = os.path.isfile('/TICI')
|
|
||||||
AGNOS = TICI
|
|
||||||
|
|
||||||
Decider('MD5-timestamp')
|
Decider('MD5-timestamp')
|
||||||
|
|
||||||
SetOption('num_jobs', int(os.cpu_count()/2))
|
SetOption('num_jobs', max(1, int(os.cpu_count()/(1 if "CI" in os.environ else 2))))
|
||||||
|
|
||||||
AddOption('--kaitai',
|
|
||||||
action='store_true',
|
|
||||||
help='Regenerate kaitai struct parsers')
|
|
||||||
|
|
||||||
AddOption('--asan',
|
|
||||||
action='store_true',
|
|
||||||
help='turn on ASAN')
|
|
||||||
|
|
||||||
AddOption('--ubsan',
|
|
||||||
action='store_true',
|
|
||||||
help='turn on UBSan')
|
|
||||||
|
|
||||||
AddOption('--coverage',
|
|
||||||
action='store_true',
|
|
||||||
help='build with test coverage options')
|
|
||||||
|
|
||||||
AddOption('--clazy',
|
|
||||||
action='store_true',
|
|
||||||
help='build with clazy')
|
|
||||||
|
|
||||||
AddOption('--compile_db',
|
|
||||||
action='store_true',
|
|
||||||
help='build clang compilation database')
|
|
||||||
|
|
||||||
AddOption('--ccflags',
|
|
||||||
action='store',
|
|
||||||
type='string',
|
|
||||||
default='',
|
|
||||||
help='pass arbitrary flags over the command line')
|
|
||||||
|
|
||||||
AddOption('--external-sconscript',
|
|
||||||
action='store',
|
|
||||||
metavar='FILE',
|
|
||||||
dest='external_sconscript',
|
|
||||||
help='add an external SConscript to the build')
|
|
||||||
|
|
||||||
AddOption('--pc-thneed',
|
|
||||||
action='store_true',
|
|
||||||
dest='pc_thneed',
|
|
||||||
help='use thneed on pc')
|
|
||||||
|
|
||||||
AddOption('--mutation',
|
|
||||||
action='store_true',
|
|
||||||
help='generate mutation-ready code')
|
|
||||||
|
|
||||||
|
AddOption('--ccflags', action='store', type='string', default='', help='pass arbitrary flags over the command line')
|
||||||
|
AddOption('--verbose', action='store_true', default=False, help='show full build commands')
|
||||||
|
release = not os.path.exists(File('#.gitattributes').abspath) # file absent on release branch, see release_files.py
|
||||||
AddOption('--minimal',
|
AddOption('--minimal',
|
||||||
action='store_false',
|
action='store_false',
|
||||||
dest='extras',
|
dest='extras',
|
||||||
default=os.path.exists(File('#.lfsconfig').abspath), # minimal by default on release branch (where there's no LFS)
|
default=(not TICI and not release),
|
||||||
help='the minimum build to run openpilot. no tests, tools, etc.')
|
help='the minimum build to run openpilot. no tests, tools, etc.')
|
||||||
|
|
||||||
## Architecture name breakdown (arch)
|
# Detect platform
|
||||||
## - larch64: linux tici aarch64
|
arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
|
||||||
## - aarch64: linux pc aarch64
|
|
||||||
## - x86_64: linux pc x64
|
|
||||||
## - Darwin: mac x64 or arm64
|
|
||||||
real_arch = arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
|
|
||||||
if platform.system() == "Darwin":
|
if platform.system() == "Darwin":
|
||||||
arch = "Darwin"
|
arch = "Darwin"
|
||||||
brew_prefix = subprocess.check_output(['brew', '--prefix'], encoding='utf8').strip()
|
elif arch == "aarch64" and TICI:
|
||||||
elif arch == "aarch64" and AGNOS:
|
|
||||||
arch = "larch64"
|
arch = "larch64"
|
||||||
assert arch in ["larch64", "aarch64", "x86_64", "Darwin"]
|
assert arch in [
|
||||||
|
"larch64", # linux tici arm64
|
||||||
|
"aarch64", # linux pc arm64
|
||||||
|
"x86_64", # linux pc x64
|
||||||
|
"Darwin", # macOS arm64 (x86 not supported)
|
||||||
|
]
|
||||||
|
|
||||||
lenv = {
|
pkg_names = ['acados', 'bzip2', 'capnproto', 'catch2', 'eigen', 'ffmpeg', 'json11', 'libjpeg', 'libyuv', 'ncurses', 'zeromq', 'zstd']
|
||||||
"PATH": os.environ['PATH'],
|
pkgs = [importlib.import_module(name) for name in pkg_names]
|
||||||
"LD_LIBRARY_PATH": [Dir(f"#third_party/acados/{arch}/lib").abspath],
|
acados = pkgs[pkg_names.index('acados')]
|
||||||
"PYTHONPATH": Dir("#").abspath + ':' + Dir(f"#third_party/acados").abspath,
|
acados_include_dirs = [
|
||||||
|
acados.INCLUDE_DIR,
|
||||||
|
os.path.join(acados.INCLUDE_DIR, "blasfeo", "include"),
|
||||||
|
os.path.join(acados.INCLUDE_DIR, "hpipm", "include"),
|
||||||
|
]
|
||||||
|
|
||||||
"ACADOS_SOURCE_DIR": Dir("#third_party/acados").abspath,
|
|
||||||
"ACADOS_PYTHON_INTERFACE_PATH": Dir("#third_party/acados/acados_template").abspath,
|
# ***** enforce a whitelist of system libraries *****
|
||||||
"TERA_PATH": Dir("#").abspath + f"/third_party/acados/{arch}/t_renderer"
|
# this prevents silently relying on a 3rd party package,
|
||||||
|
# e.g. apt-installed libusb. all libraries should either
|
||||||
|
# be distributed with all Linux distros and macOS, or
|
||||||
|
# vendored in commaai/dependencies.
|
||||||
|
allowed_system_libs = {
|
||||||
|
"EGL", "GLESv2", "GL",
|
||||||
|
"Qt5Charts", "Qt5Core", "Qt5Gui", "Qt5Widgets",
|
||||||
|
"dl", "drm", "gbm", "m", "pthread",
|
||||||
}
|
}
|
||||||
|
|
||||||
rpath = lenv["LD_LIBRARY_PATH"].copy()
|
def _resolve_lib(env, name):
|
||||||
|
for d in env.Flatten(env.get('LIBPATH', [])):
|
||||||
|
p = Dir(str(d)).abspath
|
||||||
|
for ext in ('.a', '.so', '.dylib'):
|
||||||
|
f = File(os.path.join(p, f'lib{name}{ext}'))
|
||||||
|
if f.exists() or f.has_builder():
|
||||||
|
return name
|
||||||
|
if name in allowed_system_libs:
|
||||||
|
return name
|
||||||
|
raise SCons.Errors.UserError(f"Unexpected non-vendored library '{name}'")
|
||||||
|
|
||||||
if arch == "larch64":
|
def _libflags(target, source, env, for_signature):
|
||||||
cpppath = [
|
libs = []
|
||||||
"#third_party/opencl/include",
|
lp = env.subst('$LIBLITERALPREFIX')
|
||||||
]
|
for lib in env.Flatten(env.get('LIBS', [])):
|
||||||
|
if isinstance(lib, str):
|
||||||
libpath = [
|
if os.sep in lib or lib.startswith('#'):
|
||||||
"/usr/local/lib",
|
libs.append(File(lib))
|
||||||
"/system/vendor/lib64",
|
elif lib.startswith('-') or (lp and lib.startswith(lp)):
|
||||||
"#third_party/nanovg",
|
libs.append(lib)
|
||||||
f"#third_party/acados/{arch}/lib",
|
else:
|
||||||
]
|
libs.append(_resolve_lib(env, lib))
|
||||||
|
else:
|
||||||
libpath += [
|
libs.append(lib)
|
||||||
"#third_party/libyuv/larch64/lib",
|
return _stripixes(env['LIBLINKPREFIX'], libs, env['LIBLINKSUFFIX'],
|
||||||
"/usr/lib/aarch64-linux-gnu"
|
env['LIBPREFIXES'], env['LIBSUFFIXES'], env, env['LIBLITERALPREFIX'])
|
||||||
]
|
|
||||||
cflags = ["-DQCOM2", "-mcpu=cortex-a57"]
|
|
||||||
cxxflags = ["-DQCOM2", "-mcpu=cortex-a57"]
|
|
||||||
rpath += ["/usr/local/lib"]
|
|
||||||
else:
|
|
||||||
cflags = []
|
|
||||||
cxxflags = []
|
|
||||||
cpppath = []
|
|
||||||
rpath += []
|
|
||||||
|
|
||||||
# MacOS
|
|
||||||
if arch == "Darwin":
|
|
||||||
libpath = [
|
|
||||||
f"#third_party/libyuv/{arch}/lib",
|
|
||||||
f"#third_party/acados/{arch}/lib",
|
|
||||||
f"{brew_prefix}/lib",
|
|
||||||
f"{brew_prefix}/opt/openssl@3.0/lib",
|
|
||||||
"/System/Library/Frameworks/OpenGL.framework/Libraries",
|
|
||||||
]
|
|
||||||
|
|
||||||
cflags += ["-DGL_SILENCE_DEPRECATION"]
|
|
||||||
cxxflags += ["-DGL_SILENCE_DEPRECATION"]
|
|
||||||
cpppath += [
|
|
||||||
f"{brew_prefix}/include",
|
|
||||||
f"{brew_prefix}/opt/openssl@3.0/include",
|
|
||||||
]
|
|
||||||
lenv["DYLD_LIBRARY_PATH"] = lenv["LD_LIBRARY_PATH"]
|
|
||||||
# Linux
|
|
||||||
else:
|
|
||||||
libpath = [
|
|
||||||
f"#third_party/acados/{arch}/lib",
|
|
||||||
f"#third_party/libyuv/{arch}/lib",
|
|
||||||
f"#third_party/mapbox-gl-native-qt/{arch}",
|
|
||||||
"/usr/lib",
|
|
||||||
"/usr/local/lib",
|
|
||||||
]
|
|
||||||
|
|
||||||
if GetOption('asan'):
|
|
||||||
ccflags = ["-fsanitize=address", "-fno-omit-frame-pointer"]
|
|
||||||
ldflags = ["-fsanitize=address"]
|
|
||||||
elif GetOption('ubsan'):
|
|
||||||
ccflags = ["-fsanitize=undefined"]
|
|
||||||
ldflags = ["-fsanitize=undefined"]
|
|
||||||
else:
|
|
||||||
ccflags = []
|
|
||||||
ldflags = []
|
|
||||||
|
|
||||||
# no --as-needed on mac linker
|
|
||||||
if arch != "Darwin":
|
|
||||||
ldflags += ["-Wl,--as-needed", "-Wl,--no-undefined"]
|
|
||||||
|
|
||||||
ccflags_option = GetOption('ccflags')
|
|
||||||
if ccflags_option:
|
|
||||||
ccflags += ccflags_option.split(' ')
|
|
||||||
|
|
||||||
env = Environment(
|
env = Environment(
|
||||||
ENV=lenv,
|
ENV={
|
||||||
|
"PATH": os.environ['PATH'],
|
||||||
|
"PYTHONPATH": Dir("#").abspath,
|
||||||
|
"ACADOS_SOURCE_DIR": acados.DIR,
|
||||||
|
"ACADOS_PYTHON_INTERFACE_PATH": acados.TEMPLATE_DIR,
|
||||||
|
"TERA_PATH": acados.TERA_PATH
|
||||||
|
},
|
||||||
CCFLAGS=[
|
CCFLAGS=[
|
||||||
"-g",
|
"-g",
|
||||||
"-fPIC",
|
"-fPIC",
|
||||||
"-O2",
|
"-O2",
|
||||||
"-Wunused",
|
"-Wunused",
|
||||||
"-Werror",
|
"-Werror",
|
||||||
"-Wshadow",
|
"-Wshadow" if arch in ("Darwin", "larch64") else "-Wshadow=local",
|
||||||
"-Wno-unknown-warning-option",
|
"-Wno-unknown-warning-option",
|
||||||
"-Wno-inconsistent-missing-override",
|
"-Wno-inconsistent-missing-override",
|
||||||
"-Wno-c99-designator",
|
"-Wno-c99-designator",
|
||||||
"-Wno-reorder-init-list",
|
"-Wno-reorder-init-list",
|
||||||
"-Wno-vla-cxx-extension",
|
"-Wno-vla-cxx-extension",
|
||||||
] + cflags + ccflags,
|
],
|
||||||
|
CFLAGS=["-std=gnu11"],
|
||||||
CPPPATH=cpppath + [
|
CXXFLAGS=["-std=c++1z"],
|
||||||
|
CPPPATH=[
|
||||||
"#",
|
"#",
|
||||||
"#third_party/acados/include",
|
|
||||||
"#third_party/acados/include/blasfeo/include",
|
|
||||||
"#third_party/acados/include/hpipm/include",
|
|
||||||
"#third_party/catch2/include",
|
|
||||||
"#third_party/libyuv/include",
|
|
||||||
"#third_party/json11",
|
|
||||||
"#third_party/linux/include",
|
|
||||||
"#third_party/snpe/include",
|
|
||||||
"#third_party/nanovg",
|
|
||||||
"#third_party",
|
|
||||||
"#msgq",
|
"#msgq",
|
||||||
"#third_party/maplibre-native-qt/include",
|
acados_include_dirs,
|
||||||
f"#third_party/maplibre-native-qt/{arch}/include"
|
[x.INCLUDE_DIR for x in pkgs],
|
||||||
],
|
],
|
||||||
|
LIBPATH=[
|
||||||
CC='clang',
|
|
||||||
CXX='clang++',
|
|
||||||
LINKFLAGS=ldflags,
|
|
||||||
|
|
||||||
RPATH=rpath,
|
|
||||||
|
|
||||||
CFLAGS=["-std=gnu11"] + cflags,
|
|
||||||
CXXFLAGS=["-std=c++1z"] + cxxflags,
|
|
||||||
LIBPATH=libpath + [
|
|
||||||
"#msgq_repo",
|
|
||||||
"#third_party",
|
|
||||||
"#selfdrive/pandad",
|
|
||||||
"#common",
|
"#common",
|
||||||
|
"#msgq_repo",
|
||||||
|
"#selfdrive/pandad",
|
||||||
"#rednose/helpers",
|
"#rednose/helpers",
|
||||||
|
[x.LIB_DIR for x in pkgs],
|
||||||
],
|
],
|
||||||
|
RPATH=[],
|
||||||
CYTHONCFILESUFFIX=".cpp",
|
CYTHONCFILESUFFIX=".cpp",
|
||||||
COMPILATIONDB_USE_ABSPATH=True,
|
COMPILATIONDB_USE_ABSPATH=True,
|
||||||
REDNOSE_ROOT="#",
|
REDNOSE_ROOT="#",
|
||||||
tools=["default", "cython", "compilation_db", "rednose_filter"],
|
tools=["default", "cython", "compilation_db", "rednose_filter"],
|
||||||
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
|
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
|
||||||
)
|
)
|
||||||
|
if arch != "larch64":
|
||||||
|
env['_LIBFLAGS'] = _libflags
|
||||||
|
|
||||||
if arch == "Darwin":
|
# Arch-specific flags and paths
|
||||||
# RPATH is not supported on macOS, instead use the linker flags
|
if arch == "larch64":
|
||||||
darwin_rpath_link_flags = [f"-Wl,-rpath,{path}" for path in env["RPATH"]]
|
env["CC"] = "clang"
|
||||||
env["LINKFLAGS"] += darwin_rpath_link_flags
|
env["CXX"] = "clang++"
|
||||||
|
env.Append(LIBPATH=[
|
||||||
|
"/usr/lib/aarch64-linux-gnu",
|
||||||
|
])
|
||||||
|
arch_flags = ["-D__TICI__", "-mcpu=cortex-a57", "-DQCOM2"]
|
||||||
|
env.Append(CCFLAGS=arch_flags)
|
||||||
|
env.Append(CXXFLAGS=arch_flags)
|
||||||
|
elif arch == "Darwin":
|
||||||
|
env.Append(LIBPATH=[
|
||||||
|
"/System/Library/Frameworks/OpenGL.framework/Libraries",
|
||||||
|
])
|
||||||
|
env.Append(CCFLAGS=["-DGL_SILENCE_DEPRECATION"])
|
||||||
|
env.Append(CXXFLAGS=["-DGL_SILENCE_DEPRECATION"])
|
||||||
|
|
||||||
if GetOption('compile_db'):
|
_extra_cc = shlex.split(GetOption('ccflags') or '')
|
||||||
env.CompilationDatabase('compile_commands.json')
|
if _extra_cc:
|
||||||
|
env.Append(CCFLAGS=_extra_cc)
|
||||||
|
|
||||||
# Setup cache dir
|
# no --as-needed on mac linker
|
||||||
cache_dir = '/data/scons_cache' if AGNOS else '/tmp/scons_cache'
|
if arch != "Darwin":
|
||||||
CacheDir(cache_dir)
|
env.Append(LINKFLAGS=["-Wl,--as-needed", "-Wl,--no-undefined"])
|
||||||
Clean(["."], cache_dir)
|
|
||||||
|
|
||||||
node_interval = 5
|
# Shorter build output: show brief descriptions instead of full commands.
|
||||||
node_count = 0
|
# Full command lines are still printed on failure by scons.
|
||||||
def progress_function(node):
|
if not GetOption('verbose'):
|
||||||
global node_count
|
for action, short in (
|
||||||
node_count += node_interval
|
("CC", "CC"),
|
||||||
sys.stderr.write("progress: %d\n" % node_count)
|
("CXX", "CXX"),
|
||||||
|
("LINK", "LINK"),
|
||||||
|
("SHCC", "CC"),
|
||||||
|
("SHCXX", "CXX"),
|
||||||
|
("SHLINK", "LINK"),
|
||||||
|
("AR", "AR"),
|
||||||
|
("RANLIB", "RANLIB"),
|
||||||
|
("AS", "AS"),
|
||||||
|
):
|
||||||
|
env[f"{action}COMSTR"] = f" [{short}] $TARGET"
|
||||||
|
|
||||||
if os.environ.get('SCONS_PROGRESS'):
|
# ********** Cython build environment **********
|
||||||
Progress(progress_function, interval=node_interval)
|
|
||||||
|
|
||||||
# Cython build environment
|
|
||||||
py_include = sysconfig.get_paths()['include']
|
|
||||||
envCython = env.Clone()
|
envCython = env.Clone()
|
||||||
envCython["CPPPATH"] += [py_include, np.get_include()]
|
envCython["CPPPATH"] += [sysconfig.get_paths()['include'], np.get_include()]
|
||||||
envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-shadow", "-Wno-deprecated-declarations"]
|
envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-cpp", "-Wno-shadow", "-Wno-deprecated-declarations"]
|
||||||
envCython["CCFLAGS"].remove("-Werror")
|
envCython["CCFLAGS"].remove("-Werror")
|
||||||
|
|
||||||
envCython["LIBS"] = []
|
envCython["LIBS"] = []
|
||||||
if arch == "Darwin":
|
if arch == "Darwin":
|
||||||
envCython["LINKFLAGS"] = ["-bundle", "-undefined", "dynamic_lookup"] + darwin_rpath_link_flags
|
envCython["LINKFLAGS"] = env["LINKFLAGS"] + ["-bundle", "-undefined", "dynamic_lookup"]
|
||||||
else:
|
else:
|
||||||
envCython["LINKFLAGS"] = ["-pthread", "-shared"]
|
envCython["LINKFLAGS"] = ["-pthread", "-shared"]
|
||||||
|
|
||||||
np_version = SCons.Script.Value(np.__version__)
|
np_version = SCons.Script.Value(np.__version__)
|
||||||
Export('envCython', 'np_version')
|
Export('envCython', 'np_version')
|
||||||
|
|
||||||
# Qt build environment
|
Export('env', 'arch', 'acados', 'release')
|
||||||
qt_env = env.Clone()
|
|
||||||
qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "Qml", "QuickWidgets", "Location", "Positioning", "DBus", "Xml"]
|
|
||||||
|
|
||||||
qt_libs = []
|
# Setup cache dir
|
||||||
if arch == "Darwin":
|
default_cache_dir = '/data/scons_cache' if arch == "larch64" else '/tmp/scons_cache'
|
||||||
qt_env['QTDIR'] = f"{brew_prefix}/opt/qt@5"
|
cache_dir = ARGUMENTS.get('cache_dir', default_cache_dir)
|
||||||
qt_dirs = [
|
cache_size_limit = 4e9 if "CI" in os.environ else 2e9
|
||||||
os.path.join(qt_env['QTDIR'], "include"),
|
CacheDir(cache_dir)
|
||||||
]
|
Clean(["."], cache_dir)
|
||||||
qt_dirs += [f"{qt_env['QTDIR']}/include/Qt{m}" for m in qt_modules]
|
|
||||||
qt_env["LINKFLAGS"] += ["-F" + os.path.join(qt_env['QTDIR'], "lib")]
|
|
||||||
qt_env["FRAMEWORKS"] += [f"Qt{m}" for m in qt_modules] + ["OpenGL"]
|
|
||||||
qt_env.AppendENVPath('PATH', os.path.join(qt_env['QTDIR'], "bin"))
|
|
||||||
else:
|
|
||||||
qt_install_prefix = subprocess.check_output(['qmake', '-query', 'QT_INSTALL_PREFIX'], encoding='utf8').strip()
|
|
||||||
qt_install_headers = subprocess.check_output(['qmake', '-query', 'QT_INSTALL_HEADERS'], encoding='utf8').strip()
|
|
||||||
|
|
||||||
qt_env['QTDIR'] = qt_install_prefix
|
def prune_cache_dir(target=None, source=None, env=None):
|
||||||
qt_dirs = [
|
cache_files = sorted((os.path.join(root, f) for root, _, files in os.walk(cache_dir) for f in files), key=os.path.getmtime)
|
||||||
f"{qt_install_headers}",
|
cache_size = sum(os.path.getsize(f) for f in cache_files)
|
||||||
]
|
for f in cache_files:
|
||||||
|
if cache_size < cache_size_limit:
|
||||||
|
break
|
||||||
|
cache_size -= os.path.getsize(f)
|
||||||
|
os.unlink(f)
|
||||||
|
|
||||||
qt_gui_path = os.path.join(qt_install_headers, "QtGui")
|
# ********** start building stuff **********
|
||||||
qt_gui_dirs = [d for d in os.listdir(qt_gui_path) if os.path.isdir(os.path.join(qt_gui_path, d))]
|
|
||||||
qt_dirs += [f"{qt_install_headers}/QtGui/{qt_gui_dirs[0]}/QtGui", ] if qt_gui_dirs else []
|
|
||||||
qt_dirs += [f"{qt_install_headers}/Qt{m}" for m in qt_modules]
|
|
||||||
|
|
||||||
qt_libs = [f"Qt5{m}" for m in qt_modules]
|
|
||||||
if arch == "larch64":
|
|
||||||
qt_libs += ["GLESv2", "wayland-client"]
|
|
||||||
qt_env.PrependENVPath('PATH', Dir("#third_party/qt5/larch64/bin/").abspath)
|
|
||||||
elif arch != "Darwin":
|
|
||||||
qt_libs += ["GL"]
|
|
||||||
qt_env['QT3DIR'] = qt_env['QTDIR']
|
|
||||||
|
|
||||||
# compatibility for older SCons versions
|
|
||||||
try:
|
|
||||||
qt_env.Tool('qt3')
|
|
||||||
except SCons.Errors.UserError:
|
|
||||||
qt_env.Tool('qt')
|
|
||||||
|
|
||||||
qt_env['CPPPATH'] += qt_dirs + ["#third_party/qrcode"]
|
|
||||||
qt_flags = [
|
|
||||||
"-D_REENTRANT",
|
|
||||||
"-DQT_NO_DEBUG",
|
|
||||||
"-DQT_WIDGETS_LIB",
|
|
||||||
"-DQT_GUI_LIB",
|
|
||||||
"-DQT_CORE_LIB",
|
|
||||||
"-DQT_MESSAGELOGCONTEXT",
|
|
||||||
]
|
|
||||||
qt_env['CXXFLAGS'] += qt_flags
|
|
||||||
qt_env['LIBPATH'] += ['#selfdrive/ui', f"#third_party/maplibre-native-qt/{arch}/lib"]
|
|
||||||
qt_env['RPATH'] += [Dir(f"#third_party/maplibre-native-qt/{arch}/lib").srcnode().abspath]
|
|
||||||
qt_env['LIBS'] = qt_libs
|
|
||||||
|
|
||||||
if GetOption("clazy"):
|
|
||||||
checks = [
|
|
||||||
"level0",
|
|
||||||
"level1",
|
|
||||||
"no-range-loop",
|
|
||||||
"no-non-pod-global-static",
|
|
||||||
]
|
|
||||||
qt_env['CXX'] = 'clazy'
|
|
||||||
qt_env['ENV']['CLAZY_IGNORE_DIRS'] = qt_dirs[0]
|
|
||||||
qt_env['ENV']['CLAZY_CHECKS'] = ','.join(checks)
|
|
||||||
|
|
||||||
Export('env', 'qt_env', 'arch', 'real_arch')
|
|
||||||
|
|
||||||
# Build common module
|
# Build common module
|
||||||
SConscript(['common/SConscript'])
|
SConscript(['common/SConscript'])
|
||||||
@@ -337,7 +221,6 @@ Export('common')
|
|||||||
env_swaglog = env.Clone()
|
env_swaglog = env.Clone()
|
||||||
env_swaglog['CXXFLAGS'].append('-DSWAGLOG="\\"common/swaglog.h\\""')
|
env_swaglog['CXXFLAGS'].append('-DSWAGLOG="\\"common/swaglog.h\\""')
|
||||||
SConscript(['msgq_repo/SConscript'], exports={'env': env_swaglog})
|
SConscript(['msgq_repo/SConscript'], exports={'env': env_swaglog})
|
||||||
SConscript(['opendbc_repo/SConscript'], exports={'env': env_swaglog})
|
|
||||||
|
|
||||||
SConscript(['cereal/SConscript'])
|
SConscript(['cereal/SConscript'])
|
||||||
|
|
||||||
@@ -354,28 +237,65 @@ SConscript(['rednose/SConscript'])
|
|||||||
|
|
||||||
# Build system services
|
# Build system services
|
||||||
SConscript([
|
SConscript([
|
||||||
'system/proclogd/SConscript',
|
|
||||||
'system/ubloxd/SConscript',
|
|
||||||
'system/loggerd/SConscript',
|
'system/loggerd/SConscript',
|
||||||
])
|
])
|
||||||
if arch != "Darwin":
|
|
||||||
SConscript([
|
|
||||||
'system/logcatd/SConscript',
|
|
||||||
])
|
|
||||||
|
|
||||||
if arch == "larch64":
|
if arch == "larch64":
|
||||||
SConscript(['system/camerad/SConscript'])
|
SConscript(['system/camerad/SConscript'])
|
||||||
|
|
||||||
# Build openpilot
|
# Build selfdrive
|
||||||
SConscript(['third_party/SConscript'])
|
SConscript([
|
||||||
|
'selfdrive/pandad/SConscript',
|
||||||
|
'selfdrive/controls/lib/lateral_mpc_lib/SConscript',
|
||||||
|
'selfdrive/controls/lib/longitudinal_mpc_lib/SConscript',
|
||||||
|
'selfdrive/locationd/SConscript',
|
||||||
|
'selfdrive/modeld/SConscript',
|
||||||
|
'selfdrive/ui/SConscript',
|
||||||
|
])
|
||||||
|
|
||||||
SConscript(['selfdrive/SConscript'])
|
SConscript(['sunnypilot/SConscript'])
|
||||||
|
|
||||||
if Dir('#tools/cabana/').exists() and GetOption('extras'):
|
# Build desktop-only tools
|
||||||
SConscript(['tools/replay/SConscript'])
|
if GetOption('extras') and arch != "larch64":
|
||||||
if arch != "larch64":
|
SConscript([
|
||||||
SConscript(['tools/cabana/SConscript'])
|
'tools/replay/SConscript',
|
||||||
|
'tools/cabana/SConscript',
|
||||||
|
'tools/jotpluggler/SConscript',
|
||||||
|
])
|
||||||
|
|
||||||
external_sconscript = GetOption('external_sconscript')
|
|
||||||
if external_sconscript:
|
env.CompilationDatabase('compile_commands.json')
|
||||||
SConscript([external_sconscript])
|
|
||||||
|
# progress output
|
||||||
|
def count_scons_nodes(nodes):
|
||||||
|
seen = set()
|
||||||
|
stack = list(nodes)
|
||||||
|
|
||||||
|
while stack:
|
||||||
|
node = stack.pop().disambiguate()
|
||||||
|
if node in seen:
|
||||||
|
continue
|
||||||
|
seen.add(node)
|
||||||
|
executor = node.get_executor()
|
||||||
|
if executor is not None:
|
||||||
|
stack += executor.get_all_prerequisites() + executor.get_all_children()
|
||||||
|
|
||||||
|
return len(seen)
|
||||||
|
|
||||||
|
progress_interval = 5
|
||||||
|
progress_count = 0
|
||||||
|
progress_total = max(1, count_scons_nodes(env.arg2nodes(BUILD_TARGETS or [Dir('.')], env.fs.Entry)))
|
||||||
|
|
||||||
|
def progress_function(node):
|
||||||
|
global progress_count
|
||||||
|
if progress_count >= progress_total:
|
||||||
|
return
|
||||||
|
progress_count = min(progress_count + progress_interval, progress_total)
|
||||||
|
progress = round(100. * progress_count / progress_total, 1)
|
||||||
|
sys.stderr.write("\rBuilding: %5.1f%%" % progress if sys.stderr.isatty() else "progress: %.1f\n" % progress)
|
||||||
|
if progress == 100. and sys.stderr.isatty():
|
||||||
|
sys.stderr.write("\n")
|
||||||
|
sys.stderr.flush()
|
||||||
|
|
||||||
|
Progress(progress_function, interval=progress_interval)
|
||||||
|
AddPostAction(BUILD_TARGETS or [Dir('.')], prune_cache_dir)
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
http://shind0.synology.me/carrotman/CarrotMan51.apk
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
비 루팅폰 설정
|
|
||||||
|
|
||||||
pc에 adb를 설치한다.
|
|
||||||
|
|
||||||
command prompt창에서
|
|
||||||
|
|
||||||
adb shell pm grant com.ajouatom.carrotman android.permission.READ_LOGS
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
************ 티네비설정...
|
|
||||||
|
|
||||||
권한은 모두 허가하고,
|
|
||||||
|
|
||||||
블랙박스모드를 켠다.
|
|
||||||
|
|
||||||
블랙박스 저장소를 Download 로 가서
|
|
||||||
|
|
||||||
Carrot폴더를 만든다. (여기서 만들어야한다.) 이유는 모름..
|
|
||||||
|
|
||||||
여기서 저장소 권한을 넣는다.
|
|
||||||
|
|
||||||
블백박스를 사용하지 않으면 다시 끈다.
|
|
||||||
|
|
||||||
|
|
||||||
루팅폰 잘됨~
|
|
||||||
+2
-2
@@ -4,7 +4,7 @@ cereal_dir = Dir('.')
|
|||||||
gen_dir = Dir('gen')
|
gen_dir = Dir('gen')
|
||||||
|
|
||||||
# Build cereal
|
# Build cereal
|
||||||
schema_files = ['log.capnp', 'car.capnp', 'legacy.capnp', 'custom.capnp']
|
schema_files = ['log.capnp', 'car.capnp', 'deprecated.capnp', 'custom.capnp']
|
||||||
env.Command([f'gen/cpp/{s}.c++' for s in schema_files] + [f'gen/cpp/{s}.h' for s in schema_files],
|
env.Command([f'gen/cpp/{s}.c++' for s in schema_files] + [f'gen/cpp/{s}.h' for s in schema_files],
|
||||||
schema_files,
|
schema_files,
|
||||||
f"capnpc --src-prefix={cereal_dir.path} $SOURCES -o c++:{gen_dir.path}/cpp/")
|
f"capnpc --src-prefix={cereal_dir.path} $SOURCES -o c++:{gen_dir.path}/cpp/")
|
||||||
@@ -13,7 +13,7 @@ cereal = env.Library('cereal', [f'gen/cpp/{s}.c++' for s in schema_files])
|
|||||||
|
|
||||||
# Build messaging
|
# Build messaging
|
||||||
services_h = env.Command(['services.h'], ['services.py'], 'python3 ' + cereal_dir.path + '/services.py > $TARGET')
|
services_h = env.Command(['services.h'], ['services.py'], 'python3 ' + cereal_dir.path + '/services.py > $TARGET')
|
||||||
env.Program('messaging/bridge', ['messaging/bridge.cc', 'messaging/msgq_to_zmq.cc'], LIBS=[msgq, common, 'pthread'])
|
env.Program('messaging/bridge', ['messaging/bridge.cc', 'messaging/msgq_to_zmq.cc', 'messaging/bridge_zmq.cc'], LIBS=[msgq, common, 'pthread'])
|
||||||
|
|
||||||
socketmaster = env.Library('socketmaster', ['messaging/socketmaster.cc'])
|
socketmaster = env.Library('socketmaster', ['messaging/socketmaster.cc'])
|
||||||
|
|
||||||
|
|||||||
+443
-41
@@ -10,64 +10,450 @@ $Cxx.namespace("cereal");
|
|||||||
# DO rename the structs
|
# DO rename the structs
|
||||||
# DON'T change the identifier (e.g. @0x81c2f05a394cf4af)
|
# DON'T change the identifier (e.g. @0x81c2f05a394cf4af)
|
||||||
|
|
||||||
# you can rename the struct, but don't change the identifier
|
struct ModularAssistiveDrivingSystem {
|
||||||
struct CarrotMan @0x81c2f05a394cf4af {
|
state @0 :ModularAssistiveDrivingSystemState;
|
||||||
activeCarrot @0 : Int32;
|
enabled @1 :Bool;
|
||||||
nRoadLimitSpeed @1 : Int32;
|
active @2 :Bool;
|
||||||
remote @2 : Text;
|
available @3 :Bool;
|
||||||
xSpdType @3 : Int32;
|
|
||||||
xSpdLimit @4 : Int32;
|
enum ModularAssistiveDrivingSystemState {
|
||||||
xSpdDist @5 : Int32;
|
disabled @0;
|
||||||
xSpdCountDown @6 : Int32;
|
paused @1;
|
||||||
xTurnInfo @7 : Int32;
|
enabled @2;
|
||||||
xDistToTurn @8 : Int32;
|
softDisabling @3;
|
||||||
xTurnCountDown @9 : Int32;
|
overriding @4;
|
||||||
atcType @10 : Text;
|
}
|
||||||
vTurnSpeed @11 : Int32;
|
|
||||||
szPosRoadName @12 : Text;
|
|
||||||
szTBTMainText @13 : Text;
|
|
||||||
desiredSpeed @14 : Int32;
|
|
||||||
desiredSource @15 : Text;
|
|
||||||
carrotCmdIndex @16 : Int32;
|
|
||||||
carrotCmd @17 : Text;
|
|
||||||
carrotArg @18 : Text;
|
|
||||||
xPosLat @19 : Float32;
|
|
||||||
xPosLon @20 : Float32;
|
|
||||||
xPosAngle @21 : Float32;
|
|
||||||
xPosSpeed @22 : Float32;
|
|
||||||
trafficState @23 : Int32;
|
|
||||||
nGoPosDist @24 : Int32;
|
|
||||||
nGoPosTime @25 : Int32;
|
|
||||||
szSdiDescr @26 : Text;
|
|
||||||
naviPaths @27 : Text;
|
|
||||||
leftSec @28 : Int32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved1 @0xaedffd8f31e7b55d {
|
struct IntelligentCruiseButtonManagement {
|
||||||
|
state @0 :IntelligentCruiseButtonManagementState;
|
||||||
|
sendButton @1 :SendButtonState;
|
||||||
|
vTarget @2 :Float32;
|
||||||
|
|
||||||
|
enum IntelligentCruiseButtonManagementState {
|
||||||
|
inactive @0; # No button press or default state
|
||||||
|
preActive @1; # Pre-active state before transitioning to increasing or decreasing
|
||||||
|
increasing @2; # Increasing speed
|
||||||
|
decreasing @3; # Decreasing speed
|
||||||
|
holding @4; # Holding steady speed
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SendButtonState {
|
||||||
|
none @0;
|
||||||
|
increase @1;
|
||||||
|
decrease @2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved2 @0xf35cc4560bbf6ec2 {
|
# Same struct as Log.RadarState.LeadData
|
||||||
|
struct LeadData {
|
||||||
|
dRel @0 :Float32;
|
||||||
|
yRel @1 :Float32;
|
||||||
|
vRel @2 :Float32;
|
||||||
|
aRel @3 :Float32;
|
||||||
|
vLead @4 :Float32;
|
||||||
|
dPath @6 :Float32;
|
||||||
|
vLat @7 :Float32;
|
||||||
|
vLeadK @8 :Float32;
|
||||||
|
aLeadK @9 :Float32;
|
||||||
|
fcw @10 :Bool;
|
||||||
|
status @11 :Bool;
|
||||||
|
aLeadTau @12 :Float32;
|
||||||
|
modelProb @13 :Float32;
|
||||||
|
radar @14 :Bool;
|
||||||
|
radarTrackId @15 :Int32 = -1;
|
||||||
|
|
||||||
|
aLeadDEPRECATED @5 :Float32;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved3 @0xda96579883444c35 {
|
struct SelfdriveStateSP @0x81c2f05a394cf4af {
|
||||||
|
mads @0 :ModularAssistiveDrivingSystem;
|
||||||
|
intelligentCruiseButtonManagement @1 :IntelligentCruiseButtonManagement;
|
||||||
|
|
||||||
|
enum AudibleAlert {
|
||||||
|
none @0;
|
||||||
|
|
||||||
|
engage @1;
|
||||||
|
disengage @2;
|
||||||
|
refuse @3;
|
||||||
|
|
||||||
|
warningSoft @4;
|
||||||
|
warningImmediate @5;
|
||||||
|
|
||||||
|
prompt @6;
|
||||||
|
promptRepeat @7;
|
||||||
|
promptDistracted @8;
|
||||||
|
|
||||||
|
# unused, these are reserved for upstream events so we don't collide
|
||||||
|
reserved9 @9;
|
||||||
|
reserved10 @10;
|
||||||
|
reserved11 @11;
|
||||||
|
reserved12 @12;
|
||||||
|
reserved13 @13;
|
||||||
|
reserved14 @14;
|
||||||
|
reserved15 @15;
|
||||||
|
reserved16 @16;
|
||||||
|
reserved17 @17;
|
||||||
|
reserved18 @18;
|
||||||
|
reserved19 @19;
|
||||||
|
reserved20 @20;
|
||||||
|
reserved21 @21;
|
||||||
|
reserved22 @22;
|
||||||
|
reserved23 @23;
|
||||||
|
reserved24 @24;
|
||||||
|
reserved25 @25;
|
||||||
|
reserved26 @26;
|
||||||
|
reserved27 @27;
|
||||||
|
reserved28 @28;
|
||||||
|
reserved29 @29;
|
||||||
|
reserved30 @30;
|
||||||
|
|
||||||
|
promptSingleLow @31;
|
||||||
|
promptSingleHigh @32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved4 @0x80ae746ee2596b11 {
|
struct ModelManagerSP @0xaedffd8f31e7b55d {
|
||||||
|
activeBundle @0 :ModelBundle;
|
||||||
|
selectedBundle @1 :ModelBundle;
|
||||||
|
availableBundles @2 :List(ModelBundle);
|
||||||
|
|
||||||
|
struct DownloadUri {
|
||||||
|
uri @0 :Text;
|
||||||
|
sha256 @1 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DownloadStatus {
|
||||||
|
notDownloading @0;
|
||||||
|
downloading @1;
|
||||||
|
downloaded @2;
|
||||||
|
cached @3;
|
||||||
|
failed @4;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DownloadProgress {
|
||||||
|
status @0 :DownloadStatus;
|
||||||
|
progress @1 :Float32;
|
||||||
|
eta @2 :UInt32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Artifact {
|
||||||
|
fileName @0 :Text;
|
||||||
|
downloadUri @1 :DownloadUri;
|
||||||
|
downloadProgress @2 :DownloadProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Model {
|
||||||
|
type @0 :Type;
|
||||||
|
artifact @1 :Artifact; # Main artifact
|
||||||
|
metadata @2 :Artifact; # Metadata artifact
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
supercombo @0;
|
||||||
|
navigation @1;
|
||||||
|
vision @2;
|
||||||
|
policy @3;
|
||||||
|
offPolicy @4;
|
||||||
|
onPolicy @5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Runner {
|
||||||
|
snpe @0;
|
||||||
|
tinygrad @1;
|
||||||
|
stock @2;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Override {
|
||||||
|
key @0 :Text;
|
||||||
|
value @1 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ModelBundle {
|
||||||
|
index @0 :UInt32;
|
||||||
|
internalName @1 :Text;
|
||||||
|
displayName @2 :Text;
|
||||||
|
models @3 :List(Model);
|
||||||
|
status @4 :DownloadStatus;
|
||||||
|
generation @5 :UInt32;
|
||||||
|
environment @6 :Text;
|
||||||
|
runner @7 :Runner;
|
||||||
|
is20hz @8 :Bool;
|
||||||
|
ref @9 :Text;
|
||||||
|
minimumSelectorVersion @10 :UInt32;
|
||||||
|
overrides @11 :List(Override);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved5 @0xa5cd762cd951a455 {
|
struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 {
|
||||||
|
dec @0 :DynamicExperimentalControl;
|
||||||
|
longitudinalPlanSource @1 :LongitudinalPlanSource;
|
||||||
|
smartCruiseControl @2 :SmartCruiseControl;
|
||||||
|
speedLimit @3 :SpeedLimit;
|
||||||
|
vTarget @4 :Float32;
|
||||||
|
aTarget @5 :Float32;
|
||||||
|
events @6 :List(OnroadEventSP.Event);
|
||||||
|
e2eAlerts @7 :E2eAlerts;
|
||||||
|
|
||||||
|
struct DynamicExperimentalControl {
|
||||||
|
state @0 :DynamicExperimentalControlState;
|
||||||
|
enabled @1 :Bool;
|
||||||
|
active @2 :Bool;
|
||||||
|
|
||||||
|
enum DynamicExperimentalControlState {
|
||||||
|
acc @0;
|
||||||
|
blended @1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SmartCruiseControl {
|
||||||
|
vision @0 :Vision;
|
||||||
|
map @1 :Map;
|
||||||
|
|
||||||
|
struct Vision {
|
||||||
|
state @0 :VisionState;
|
||||||
|
vTarget @1 :Float32;
|
||||||
|
aTarget @2 :Float32;
|
||||||
|
currentLateralAccel @3 :Float32;
|
||||||
|
maxPredictedLateralAccel @4 :Float32;
|
||||||
|
enabled @5 :Bool;
|
||||||
|
active @6 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map {
|
||||||
|
state @0 :MapState;
|
||||||
|
vTarget @1 :Float32;
|
||||||
|
aTarget @2 :Float32;
|
||||||
|
enabled @3 :Bool;
|
||||||
|
active @4 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum VisionState {
|
||||||
|
disabled @0; # System disabled or inactive.
|
||||||
|
enabled @1; # No predicted substantial turn on vision range.
|
||||||
|
entering @2; # A substantial turn is predicted ahead, adapting speed to turn comfort levels.
|
||||||
|
turning @3; # Actively turning. Managing acceleration to provide a roll on turn feeling.
|
||||||
|
leaving @4; # Road ahead straightens. Start to allow positive acceleration.
|
||||||
|
overriding @5; # System overriding with manual control.
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MapState {
|
||||||
|
disabled @0; # System disabled or inactive.
|
||||||
|
enabled @1; # No predicted substantial turn on map range.
|
||||||
|
turning @2; # Actively turning. Managing acceleration to provide a roll on turn feeling.
|
||||||
|
overriding @3; # System overriding with manual control.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SpeedLimit {
|
||||||
|
resolver @0 :Resolver;
|
||||||
|
assist @1 :Assist;
|
||||||
|
|
||||||
|
struct Resolver {
|
||||||
|
speedLimit @0 :Float32;
|
||||||
|
distToSpeedLimit @1 :Float32;
|
||||||
|
source @2 :Source;
|
||||||
|
speedLimitOffset @3 :Float32;
|
||||||
|
speedLimitLast @4 :Float32;
|
||||||
|
speedLimitFinal @5 :Float32;
|
||||||
|
speedLimitFinalLast @6 :Float32;
|
||||||
|
speedLimitValid @7 :Bool;
|
||||||
|
speedLimitLastValid @8 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Assist {
|
||||||
|
state @0 :AssistState;
|
||||||
|
enabled @1 :Bool;
|
||||||
|
active @2 :Bool;
|
||||||
|
vTarget @3 :Float32;
|
||||||
|
aTarget @4 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Source {
|
||||||
|
none @0;
|
||||||
|
car @1;
|
||||||
|
map @2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AssistState {
|
||||||
|
disabled @0;
|
||||||
|
inactive @1; # No speed limit set or not enabled by parameter.
|
||||||
|
preActive @2;
|
||||||
|
pending @3; # Awaiting new speed limit.
|
||||||
|
adapting @4; # Reducing speed to match new speed limit.
|
||||||
|
active @5; # Cruising at speed limit.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LongitudinalPlanSource {
|
||||||
|
cruise @0;
|
||||||
|
sccVision @1;
|
||||||
|
sccMap @2;
|
||||||
|
speedLimitAssist @3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct E2eAlerts {
|
||||||
|
greenLightAlert @0 :Bool;
|
||||||
|
leadDepartAlert @1 :Bool;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved6 @0xf98d843bfd7004a3 {
|
struct OnroadEventSP @0xda96579883444c35 {
|
||||||
|
events @0 :List(Event);
|
||||||
|
|
||||||
|
struct Event {
|
||||||
|
name @0 :EventName;
|
||||||
|
|
||||||
|
# event types
|
||||||
|
enable @1 :Bool;
|
||||||
|
noEntry @2 :Bool;
|
||||||
|
warning @3 :Bool; # alerts presented only when enabled or soft disabling
|
||||||
|
userDisable @4 :Bool;
|
||||||
|
softDisable @5 :Bool;
|
||||||
|
immediateDisable @6 :Bool;
|
||||||
|
preEnable @7 :Bool;
|
||||||
|
permanent @8 :Bool; # alerts presented regardless of openpilot state
|
||||||
|
overrideLateral @10 :Bool;
|
||||||
|
overrideLongitudinal @9 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EventName {
|
||||||
|
lkasEnable @0;
|
||||||
|
lkasDisable @1;
|
||||||
|
manualSteeringRequired @2;
|
||||||
|
manualLongitudinalRequired @3;
|
||||||
|
silentLkasEnable @4;
|
||||||
|
silentLkasDisable @5;
|
||||||
|
silentBrakeHold @6;
|
||||||
|
silentWrongGear @7;
|
||||||
|
silentReverseGear @8;
|
||||||
|
silentDoorOpen @9;
|
||||||
|
silentSeatbeltNotLatched @10;
|
||||||
|
silentParkBrake @11;
|
||||||
|
controlsMismatchLateral @12;
|
||||||
|
hyundaiRadarTracksConfirmed @13;
|
||||||
|
experimentalModeSwitched @14;
|
||||||
|
wrongCarModeAlertOnly @15;
|
||||||
|
pedalPressedAlertOnly @16;
|
||||||
|
laneTurnLeft @17;
|
||||||
|
laneTurnRight @18;
|
||||||
|
speedLimitPreActive @19;
|
||||||
|
speedLimitActive @20;
|
||||||
|
speedLimitChanged @21;
|
||||||
|
speedLimitPending @22;
|
||||||
|
e2eChime @23;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved7 @0xb86e6369214c01c8 {
|
struct CarParamsSP @0x80ae746ee2596b11 {
|
||||||
|
flags @0 :UInt32; # flags for car specific quirks in sunnypilot
|
||||||
|
safetyParam @1 : Int16; # flags for sunnypilot's custom safety flags
|
||||||
|
pcmCruiseSpeed @3 :Bool;
|
||||||
|
intelligentCruiseButtonManagementAvailable @4 :Bool;
|
||||||
|
enableGasInterceptor @5 :Bool;
|
||||||
|
|
||||||
|
neuralNetworkLateralControl @2 :NeuralNetworkLateralControl;
|
||||||
|
|
||||||
|
struct NeuralNetworkLateralControl {
|
||||||
|
model @0 :Model;
|
||||||
|
fuzzyFingerprint @1 :Bool;
|
||||||
|
|
||||||
|
struct Model {
|
||||||
|
path @0 :Text;
|
||||||
|
name @1 :Text;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved8 @0xf416ec09499d9d19 {
|
struct CarControlSP @0xa5cd762cd951a455 {
|
||||||
|
mads @0 :ModularAssistiveDrivingSystem;
|
||||||
|
params @1 :List(Param);
|
||||||
|
leadOne @2 :LeadData;
|
||||||
|
leadTwo @3 :LeadData;
|
||||||
|
intelligentCruiseButtonManagement @4 :IntelligentCruiseButtonManagement;
|
||||||
|
|
||||||
|
struct Param {
|
||||||
|
key @0 :Text;
|
||||||
|
type @2 :ParamType;
|
||||||
|
value @3 :Data;
|
||||||
|
|
||||||
|
valueDEPRECATED @1 :Text; # The data type change may cause issues with backwards compatibility.
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ParamType {
|
||||||
|
string @0;
|
||||||
|
bool @1;
|
||||||
|
int @2;
|
||||||
|
float @3;
|
||||||
|
time @4;
|
||||||
|
json @5;
|
||||||
|
bytes @6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved9 @0xa1680744031fdb2d {
|
struct BackupManagerSP @0xf98d843bfd7004a3 {
|
||||||
|
backupStatus @0 :Status;
|
||||||
|
restoreStatus @1 :Status;
|
||||||
|
backupProgress @2 :Float32;
|
||||||
|
restoreProgress @3 :Float32;
|
||||||
|
lastError @4 :Text;
|
||||||
|
currentBackup @5 :BackupInfo;
|
||||||
|
backupHistory @6 :List(BackupInfo);
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
idle @0;
|
||||||
|
inProgress @1;
|
||||||
|
completed @2;
|
||||||
|
failed @3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Version {
|
||||||
|
major @0 :UInt16;
|
||||||
|
minor @1 :UInt16;
|
||||||
|
patch @2 :UInt16;
|
||||||
|
build @3 :UInt16;
|
||||||
|
branch @4 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MetadataEntry {
|
||||||
|
key @0 :Text;
|
||||||
|
value @1 :Text;
|
||||||
|
tags @2 :List(Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BackupInfo {
|
||||||
|
deviceId @0 :Text;
|
||||||
|
version @1 :UInt32;
|
||||||
|
config @2 :Text;
|
||||||
|
isEncrypted @3 :Bool;
|
||||||
|
createdAt @4 :Text; # ISO timestamp
|
||||||
|
updatedAt @5 :Text; # ISO timestamp
|
||||||
|
sunnypilotVersion @6 :Version;
|
||||||
|
backupMetadata @7 :List(MetadataEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CarStateSP @0xb86e6369214c01c8 {
|
||||||
|
speedLimit @0 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LiveMapDataSP @0xf416ec09499d9d19 {
|
||||||
|
speedLimitValid @0 :Bool;
|
||||||
|
speedLimit @1 :Float32;
|
||||||
|
speedLimitAheadValid @2 :Bool;
|
||||||
|
speedLimitAhead @3 :Float32;
|
||||||
|
speedLimitAheadDistance @4 :Float32;
|
||||||
|
roadName @5 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ModelDataV2SP @0xa1680744031fdb2d {
|
||||||
|
laneTurnDirection @0 :TurnDirection;
|
||||||
|
|
||||||
|
enum TurnDirection {
|
||||||
|
none @0;
|
||||||
|
turnLeft @1;
|
||||||
|
turnRight @2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved10 @0xcb9fd56c7057593a {
|
struct CustomReserved10 @0xcb9fd56c7057593a {
|
||||||
@@ -97,5 +483,21 @@ struct CustomReserved17 @0xa30662f84033036c {
|
|||||||
struct CustomReserved18 @0xc86a3d38d13eb3ef {
|
struct CustomReserved18 @0xc86a3d38d13eb3ef {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved19 @0xa4f1eb3323f5f582 {
|
struct LiveCurvatureParameters @0xa4f1eb3323f5f582 {
|
||||||
|
liveValid @0 :Bool;
|
||||||
|
version @1 :Int32;
|
||||||
|
useParams @2 :Bool;
|
||||||
|
currentCorrection @3 :Float32;
|
||||||
|
currentBias @4 :Float32;
|
||||||
|
currentBucketPoints @5 :UInt16;
|
||||||
|
totalBucketPoints @6 :UInt16;
|
||||||
|
calPerc @7 :Int8;
|
||||||
|
bucketSpeed @8 :Int8;
|
||||||
|
corrections @9 :List(Float32);
|
||||||
|
counts @10 :List(UInt16);
|
||||||
|
biases @11 :List(Float32);
|
||||||
|
bucketCurvature @12 :Int8;
|
||||||
|
fitValid @13 :List(Bool);
|
||||||
|
previewCorrections @14 :List(Float32);
|
||||||
|
previewValid @15 :List(Bool);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,777 @@
|
|||||||
|
using Cxx = import "./include/c++.capnp";
|
||||||
|
$Cxx.namespace("cereal");
|
||||||
|
|
||||||
|
@0x80ef1ec4889c2a63;
|
||||||
|
|
||||||
|
# deprecated.capnp: a home for deprecated structs
|
||||||
|
|
||||||
|
struct LogRotate @0x9811e1f38f62f2d1 {
|
||||||
|
segmentNum @0 :Int32;
|
||||||
|
path @1 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LiveUI @0xc08240f996aefced {
|
||||||
|
rearViewCam @0 :Bool;
|
||||||
|
alertText1 @1 :Text;
|
||||||
|
alertText2 @2 :Text;
|
||||||
|
awarenessStatus @3 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct UiLayoutState @0x88dcce08ad29dda0 {
|
||||||
|
activeApp @0 :App;
|
||||||
|
sidebarCollapsed @1 :Bool;
|
||||||
|
mapEnabled @2 :Bool;
|
||||||
|
mockEngaged @3 :Bool;
|
||||||
|
|
||||||
|
enum App @0x9917470acf94d285 {
|
||||||
|
home @0;
|
||||||
|
music @1;
|
||||||
|
nav @2;
|
||||||
|
settings @3;
|
||||||
|
none @4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OrbslamCorrection @0x8afd33dc9b35e1aa {
|
||||||
|
correctionMonoTime @0 :UInt64;
|
||||||
|
prePositionECEF @1 :List(Float64);
|
||||||
|
postPositionECEF @2 :List(Float64);
|
||||||
|
prePoseQuatECEF @3 :List(Float32);
|
||||||
|
postPoseQuatECEF @4 :List(Float32);
|
||||||
|
numInliers @5 :UInt32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EthernetPacket @0xa99a9d5b33cf5859 {
|
||||||
|
pkt @0 :Data;
|
||||||
|
ts @1 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CellInfo @0xcff7566681c277ce {
|
||||||
|
timestamp @0 :UInt64;
|
||||||
|
repr @1 :Text; # android toString() for now
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WifiScan @0xd4df5a192382ba0b {
|
||||||
|
bssid @0 :Text;
|
||||||
|
ssid @1 :Text;
|
||||||
|
capabilities @2 :Text;
|
||||||
|
frequency @3 :Int32;
|
||||||
|
level @4 :Int32;
|
||||||
|
timestamp @5 :Int64;
|
||||||
|
|
||||||
|
centerFreq0 @6 :Int32;
|
||||||
|
centerFreq1 @7 :Int32;
|
||||||
|
channelWidth @8 :ChannelWidth;
|
||||||
|
operatorFriendlyName @9 :Text;
|
||||||
|
venueName @10 :Text;
|
||||||
|
is80211mcResponder @11 :Bool;
|
||||||
|
passpoint @12 :Bool;
|
||||||
|
|
||||||
|
distanceCm @13 :Int32;
|
||||||
|
distanceSdCm @14 :Int32;
|
||||||
|
|
||||||
|
enum ChannelWidth @0xcb6a279f015f6b51 {
|
||||||
|
w20Mhz @0;
|
||||||
|
w40Mhz @1;
|
||||||
|
w80Mhz @2;
|
||||||
|
w160Mhz @3;
|
||||||
|
w80Plus80Mhz @4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LiveEventData @0x94b7baa90c5c321e {
|
||||||
|
name @0 :Text;
|
||||||
|
value @1 :Int32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ModelData @0xb8aad62cffef28a9 {
|
||||||
|
frameId @0 :UInt32;
|
||||||
|
frameAge @12 :UInt32;
|
||||||
|
frameDropPerc @13 :Float32;
|
||||||
|
timestampEof @9 :UInt64;
|
||||||
|
modelExecutionTime @14 :Float32;
|
||||||
|
gpuExecutionTime @16 :Float32;
|
||||||
|
rawPred @15 :Data;
|
||||||
|
|
||||||
|
path @1 :PathData;
|
||||||
|
leftLane @2 :PathData;
|
||||||
|
rightLane @3 :PathData;
|
||||||
|
lead @4 :LeadData;
|
||||||
|
freePath @6 :List(Float32);
|
||||||
|
|
||||||
|
settings @5 :ModelSettings;
|
||||||
|
leadFuture @7 :LeadData;
|
||||||
|
speed @8 :List(Float32);
|
||||||
|
meta @10 :MetaData;
|
||||||
|
longitudinal @11 :LongitudinalData;
|
||||||
|
|
||||||
|
struct PathData @0x8817eeea389e9f08 {
|
||||||
|
points @0 :List(Float32);
|
||||||
|
prob @1 :Float32;
|
||||||
|
std @2 :Float32;
|
||||||
|
stds @3 :List(Float32);
|
||||||
|
poly @4 :List(Float32);
|
||||||
|
validLen @5 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LeadData @0xd1c9bef96d26fa91 {
|
||||||
|
dist @0 :Float32;
|
||||||
|
prob @1 :Float32;
|
||||||
|
std @2 :Float32;
|
||||||
|
relVel @3 :Float32;
|
||||||
|
relVelStd @4 :Float32;
|
||||||
|
relY @5 :Float32;
|
||||||
|
relYStd @6 :Float32;
|
||||||
|
relA @7 :Float32;
|
||||||
|
relAStd @8 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ModelSettings @0xa26e3710efd3e914 {
|
||||||
|
bigBoxX @0 :UInt16;
|
||||||
|
bigBoxY @1 :UInt16;
|
||||||
|
bigBoxWidth @2 :UInt16;
|
||||||
|
bigBoxHeight @3 :UInt16;
|
||||||
|
boxProjection @4 :List(Float32);
|
||||||
|
yuvCorrection @5 :List(Float32);
|
||||||
|
inputTransform @6 :List(Float32);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MetaData @0x9744f25fb60f2bf8 {
|
||||||
|
engagedProb @0 :Float32;
|
||||||
|
desirePrediction @1 :List(Float32);
|
||||||
|
brakeDisengageProb @2 :Float32;
|
||||||
|
gasDisengageProb @3 :Float32;
|
||||||
|
steerOverrideProb @4 :Float32;
|
||||||
|
desireState @5 :List(Float32);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LongitudinalData @0xf98f999c6a071122 {
|
||||||
|
distances @2 :List(Float32);
|
||||||
|
speeds @0 :List(Float32);
|
||||||
|
accelerations @1 :List(Float32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ECEFPoint @0xc25bbbd524983447 {
|
||||||
|
x @0 :Float64;
|
||||||
|
y @1 :Float64;
|
||||||
|
z @2 :Float64;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ECEFPointDEPRECATED @0xe10e21168db0c7f7 {
|
||||||
|
x @0 :Float32;
|
||||||
|
y @1 :Float32;
|
||||||
|
z @2 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GPSPlannerPoints @0xab54c59699f8f9f3 {
|
||||||
|
curPosDEPRECATED @0 :ECEFPointDEPRECATED;
|
||||||
|
pointsDEPRECATED @1 :List(ECEFPointDEPRECATED);
|
||||||
|
curPos @6 :ECEFPoint;
|
||||||
|
points @7 :List(ECEFPoint);
|
||||||
|
valid @2 :Bool;
|
||||||
|
trackName @3 :Text;
|
||||||
|
speedLimit @4 :Float32;
|
||||||
|
accelTarget @5 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GPSPlannerPlan @0xf5ad1d90cdc1dd6b {
|
||||||
|
valid @0 :Bool;
|
||||||
|
poly @1 :List(Float32);
|
||||||
|
trackName @2 :Text;
|
||||||
|
speed @3 :Float32;
|
||||||
|
acceleration @4 :Float32;
|
||||||
|
pointsDEPRECATED @5 :List(ECEFPointDEPRECATED);
|
||||||
|
points @6 :List(ECEFPoint);
|
||||||
|
xLookahead @7 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct UiNavigationEvent @0x90c8426c3eaddd3b {
|
||||||
|
type @0: Type;
|
||||||
|
status @1: Status;
|
||||||
|
distanceTo @2: Float32;
|
||||||
|
endRoadPointDEPRECATED @3: ECEFPointDEPRECATED;
|
||||||
|
endRoadPoint @4: ECEFPoint;
|
||||||
|
|
||||||
|
enum Type @0xe8db07dcf8fcea05 {
|
||||||
|
none @0;
|
||||||
|
laneChangeLeft @1;
|
||||||
|
laneChangeRight @2;
|
||||||
|
mergeLeft @3;
|
||||||
|
mergeRight @4;
|
||||||
|
turnLeft @5;
|
||||||
|
turnRight @6;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Status @0xb9aa88c75ef99a1f {
|
||||||
|
none @0;
|
||||||
|
passive @1;
|
||||||
|
approaching @2;
|
||||||
|
active @3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LiveLocationData @0xb99b2bc7a57e8128 {
|
||||||
|
status @0 :UInt8;
|
||||||
|
|
||||||
|
# 3D fix
|
||||||
|
lat @1 :Float64;
|
||||||
|
lon @2 :Float64;
|
||||||
|
alt @3 :Float32; # m
|
||||||
|
|
||||||
|
# speed
|
||||||
|
speed @4 :Float32; # m/s
|
||||||
|
|
||||||
|
# NED velocity components
|
||||||
|
vNED @5 :List(Float32);
|
||||||
|
|
||||||
|
# roll, pitch, heading (x,y,z)
|
||||||
|
roll @6 :Float32; # WRT to center of earth?
|
||||||
|
pitch @7 :Float32; # WRT to center of earth?
|
||||||
|
heading @8 :Float32; # WRT to north?
|
||||||
|
|
||||||
|
# what are these?
|
||||||
|
wanderAngle @9 :Float32;
|
||||||
|
trackAngle @10 :Float32;
|
||||||
|
|
||||||
|
# car frame -- https://upload.wikimedia.org/wikipedia/commons/f/f5/RPY_angles_of_cars.png
|
||||||
|
|
||||||
|
# gyro, in car frame, deg/s
|
||||||
|
gyro @11 :List(Float32);
|
||||||
|
|
||||||
|
# accel, in car frame, m/s^2
|
||||||
|
accel @12 :List(Float32);
|
||||||
|
|
||||||
|
accuracy @13 :Accuracy;
|
||||||
|
|
||||||
|
source @14 :SensorSource;
|
||||||
|
# if we are fixing a location in the past
|
||||||
|
fixMonoTime @15 :UInt64;
|
||||||
|
|
||||||
|
gpsWeek @16 :Int32;
|
||||||
|
timeOfWeek @17 :Float64;
|
||||||
|
|
||||||
|
positionECEF @18 :List(Float64);
|
||||||
|
poseQuatECEF @19 :List(Float32);
|
||||||
|
pitchCalibration @20 :Float32;
|
||||||
|
yawCalibration @21 :Float32;
|
||||||
|
imuFrame @22 :List(Float32);
|
||||||
|
|
||||||
|
struct Accuracy @0x943dc4625473b03f {
|
||||||
|
pNEDError @0 :List(Float32);
|
||||||
|
vNEDError @1 :List(Float32);
|
||||||
|
rollError @2 :Float32;
|
||||||
|
pitchError @3 :Float32;
|
||||||
|
headingError @4 :Float32;
|
||||||
|
ellipsoidSemiMajorError @5 :Float32;
|
||||||
|
ellipsoidSemiMinorError @6 :Float32;
|
||||||
|
ellipsoidOrientationError @7 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SensorSource @0xc871d3cc252af657 {
|
||||||
|
applanix @0;
|
||||||
|
kalman @1;
|
||||||
|
orbslam @2;
|
||||||
|
timing @3;
|
||||||
|
dummy @4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OrbOdometry @0xd7700859ed1f5b76 {
|
||||||
|
# timing first
|
||||||
|
startMonoTime @0 :UInt64;
|
||||||
|
endMonoTime @1 :UInt64;
|
||||||
|
|
||||||
|
# fundamental matrix and error
|
||||||
|
f @2: List(Float64);
|
||||||
|
err @3: Float64;
|
||||||
|
|
||||||
|
# number of inlier points
|
||||||
|
inliers @4: Int32;
|
||||||
|
|
||||||
|
# for debug only
|
||||||
|
# indexed by endMonoTime features
|
||||||
|
# value is startMonoTime feature match
|
||||||
|
# -1 if no match
|
||||||
|
matches @5: List(Int16);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OrbFeatures @0xcd60164a8a0159ef {
|
||||||
|
timestampEof @0 :UInt64;
|
||||||
|
# transposed arrays of normalized image coordinates
|
||||||
|
# len(xs) == len(ys) == len(descriptors) * 32
|
||||||
|
xs @1 :List(Float32);
|
||||||
|
ys @2 :List(Float32);
|
||||||
|
descriptors @3 :Data;
|
||||||
|
octaves @4 :List(Int8);
|
||||||
|
|
||||||
|
# match index to last OrbFeatures
|
||||||
|
# -1 if no match
|
||||||
|
timestampLastEof @5 :UInt64;
|
||||||
|
matches @6: List(Int16);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OrbFeaturesSummary @0xd500d30c5803fa4f {
|
||||||
|
timestampEof @0 :UInt64;
|
||||||
|
timestampLastEof @1 :UInt64;
|
||||||
|
|
||||||
|
featureCount @2 :UInt16;
|
||||||
|
matchCount @3 :UInt16;
|
||||||
|
computeNs @4 :UInt64;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OrbKeyFrame @0xc8233c0345e27e24 {
|
||||||
|
# this is a globally unique id for the KeyFrame
|
||||||
|
id @0: UInt64;
|
||||||
|
|
||||||
|
# this is the location of the KeyFrame
|
||||||
|
pos @1: ECEFPoint;
|
||||||
|
|
||||||
|
# these are the features in the world
|
||||||
|
# len(dpos) == len(descriptors) * 32
|
||||||
|
dpos @2 :List(ECEFPoint);
|
||||||
|
descriptors @3 :Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct KalmanOdometry @0x92e21bb7ea38793a {
|
||||||
|
trans @0 :List(Float32); # m/s in device frame
|
||||||
|
rot @1 :List(Float32); # rad/s in device frame
|
||||||
|
transStd @2 :List(Float32); # std m/s in device frame
|
||||||
|
rotStd @3 :List(Float32); # std rad/s in device frame
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OrbObservation @0x9b326d4e436afec7 {
|
||||||
|
observationMonoTime @0 :UInt64;
|
||||||
|
normalizedCoordinates @1 :List(Float32);
|
||||||
|
locationECEF @2 :List(Float64);
|
||||||
|
matchDistance @3: UInt32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CalibrationFeatures @0x8fdfadb254ea867a {
|
||||||
|
frameId @0 :UInt32;
|
||||||
|
|
||||||
|
p0 @1 :List(Float32);
|
||||||
|
p1 @2 :List(Float32);
|
||||||
|
status @3 :List(Int8);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NavStatus @0xbd8822120928120c {
|
||||||
|
isNavigating @0 :Bool;
|
||||||
|
currentAddress @1 :Address;
|
||||||
|
|
||||||
|
struct Address @0xce7cd672cacc7814 {
|
||||||
|
title @0 :Text;
|
||||||
|
lat @1 :Float64;
|
||||||
|
lng @2 :Float64;
|
||||||
|
house @3 :Text;
|
||||||
|
address @4 :Text;
|
||||||
|
street @5 :Text;
|
||||||
|
city @6 :Text;
|
||||||
|
state @7 :Text;
|
||||||
|
country @8 :Text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NavUpdate @0xdb98be6565516acb {
|
||||||
|
isNavigating @0 :Bool;
|
||||||
|
curSegment @1 :Int32;
|
||||||
|
segments @2 :List(Segment);
|
||||||
|
|
||||||
|
struct LatLng @0x9eaef9187cadbb9b {
|
||||||
|
lat @0 :Float64;
|
||||||
|
lng @1 :Float64;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Segment @0xa5b39b4fc4d7da3f {
|
||||||
|
from @0 :LatLng;
|
||||||
|
to @1 :LatLng;
|
||||||
|
updateTime @2 :Int32;
|
||||||
|
distance @3 :Int32;
|
||||||
|
crossTime @4 :Int32;
|
||||||
|
exitNo @5 :Int32;
|
||||||
|
instruction @6 :Instruction;
|
||||||
|
|
||||||
|
parts @7 :List(LatLng);
|
||||||
|
|
||||||
|
enum Instruction @0xc5417a637451246f {
|
||||||
|
turnLeft @0;
|
||||||
|
turnRight @1;
|
||||||
|
keepLeft @2;
|
||||||
|
keepRight @3;
|
||||||
|
straight @4;
|
||||||
|
roundaboutExitNumber @5;
|
||||||
|
roundaboutExit @6;
|
||||||
|
roundaboutTurnLeft @7;
|
||||||
|
unkn8 @8;
|
||||||
|
roundaboutStraight @9;
|
||||||
|
unkn10 @10;
|
||||||
|
roundaboutTurnRight @11;
|
||||||
|
unkn12 @12;
|
||||||
|
roundaboutUturn @13;
|
||||||
|
unkn14 @14;
|
||||||
|
arrive @15;
|
||||||
|
exitLeft @16;
|
||||||
|
exitRight @17;
|
||||||
|
unkn18 @18;
|
||||||
|
uturn @19;
|
||||||
|
# ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TrafficEvent @0xacfa74a094e62626 {
|
||||||
|
type @0 :Type;
|
||||||
|
distance @1 :Float32;
|
||||||
|
action @2 :Action;
|
||||||
|
resuming @3 :Bool;
|
||||||
|
|
||||||
|
enum Type @0xd85d75253435bf4b {
|
||||||
|
stopSign @0;
|
||||||
|
lightRed @1;
|
||||||
|
lightYellow @2;
|
||||||
|
lightGreen @3;
|
||||||
|
stopLight @4;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Action @0xa6f6ce72165ccb49 {
|
||||||
|
none @0;
|
||||||
|
yield @1;
|
||||||
|
stop @2;
|
||||||
|
resumeReady @3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct AndroidGnss @0xdfdf30d03fc485bd {
|
||||||
|
union {
|
||||||
|
measurements @0 :Measurements;
|
||||||
|
navigationMessage @1 :NavigationMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Measurements @0xa20710d4f428d6cd {
|
||||||
|
clock @0 :Clock;
|
||||||
|
measurements @1 :List(Measurement);
|
||||||
|
|
||||||
|
struct Clock @0xa0e27b453a38f450 {
|
||||||
|
timeNanos @0 :Int64;
|
||||||
|
hardwareClockDiscontinuityCount @1 :Int32;
|
||||||
|
|
||||||
|
hasTimeUncertaintyNanos @2 :Bool;
|
||||||
|
timeUncertaintyNanos @3 :Float64;
|
||||||
|
|
||||||
|
hasLeapSecond @4 :Bool;
|
||||||
|
leapSecond @5 :Int32;
|
||||||
|
|
||||||
|
hasFullBiasNanos @6 :Bool;
|
||||||
|
fullBiasNanos @7 :Int64;
|
||||||
|
|
||||||
|
hasBiasNanos @8 :Bool;
|
||||||
|
biasNanos @9 :Float64;
|
||||||
|
|
||||||
|
hasBiasUncertaintyNanos @10 :Bool;
|
||||||
|
biasUncertaintyNanos @11 :Float64;
|
||||||
|
|
||||||
|
hasDriftNanosPerSecond @12 :Bool;
|
||||||
|
driftNanosPerSecond @13 :Float64;
|
||||||
|
|
||||||
|
hasDriftUncertaintyNanosPerSecond @14 :Bool;
|
||||||
|
driftUncertaintyNanosPerSecond @15 :Float64;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Measurement @0xd949bf717d77614d {
|
||||||
|
svId @0 :Int32;
|
||||||
|
constellation @1 :Constellation;
|
||||||
|
|
||||||
|
timeOffsetNanos @2 :Float64;
|
||||||
|
state @3 :Int32;
|
||||||
|
receivedSvTimeNanos @4 :Int64;
|
||||||
|
receivedSvTimeUncertaintyNanos @5 :Int64;
|
||||||
|
cn0DbHz @6 :Float64;
|
||||||
|
pseudorangeRateMetersPerSecond @7 :Float64;
|
||||||
|
pseudorangeRateUncertaintyMetersPerSecond @8 :Float64;
|
||||||
|
accumulatedDeltaRangeState @9 :Int32;
|
||||||
|
accumulatedDeltaRangeMeters @10 :Float64;
|
||||||
|
accumulatedDeltaRangeUncertaintyMeters @11 :Float64;
|
||||||
|
|
||||||
|
hasCarrierFrequencyHz @12 :Bool;
|
||||||
|
carrierFrequencyHz @13 :Float32;
|
||||||
|
hasCarrierCycles @14 :Bool;
|
||||||
|
carrierCycles @15 :Int64;
|
||||||
|
hasCarrierPhase @16 :Bool;
|
||||||
|
carrierPhase @17 :Float64;
|
||||||
|
hasCarrierPhaseUncertainty @18 :Bool;
|
||||||
|
carrierPhaseUncertainty @19 :Float64;
|
||||||
|
hasSnrInDb @20 :Bool;
|
||||||
|
snrInDb @21 :Float64;
|
||||||
|
|
||||||
|
multipathIndicator @22 :MultipathIndicator;
|
||||||
|
|
||||||
|
enum Constellation @0x9ef1f3ff0deb5ffb {
|
||||||
|
unknown @0;
|
||||||
|
gps @1;
|
||||||
|
sbas @2;
|
||||||
|
glonass @3;
|
||||||
|
qzss @4;
|
||||||
|
beidou @5;
|
||||||
|
galileo @6;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum State @0xcbb9490adce12d72 {
|
||||||
|
unknown @0;
|
||||||
|
codeLock @1;
|
||||||
|
bitSync @2;
|
||||||
|
subframeSync @3;
|
||||||
|
towDecoded @4;
|
||||||
|
msecAmbiguous @5;
|
||||||
|
symbolSync @6;
|
||||||
|
gloStringSync @7;
|
||||||
|
gloTodDecoded @8;
|
||||||
|
bdsD2BitSync @9;
|
||||||
|
bdsD2SubframeSync @10;
|
||||||
|
galE1bcCodeLock @11;
|
||||||
|
galE1c2ndCodeLock @12;
|
||||||
|
galE1bPageSync @13;
|
||||||
|
sbasSync @14;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MultipathIndicator @0xc04e7b6231d4caa8 {
|
||||||
|
unknown @0;
|
||||||
|
detected @1;
|
||||||
|
notDetected @2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NavigationMessage @0xe2517b083095fd4e {
|
||||||
|
type @0 :Int32;
|
||||||
|
svId @1 :Int32;
|
||||||
|
messageId @2 :Int32;
|
||||||
|
submessageId @3 :Int32;
|
||||||
|
data @4 :Data;
|
||||||
|
status @5 :Status;
|
||||||
|
|
||||||
|
enum Status @0xec1ff7996b35366f {
|
||||||
|
unknown @0;
|
||||||
|
parityPassed @1;
|
||||||
|
parityRebuilt @2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LidarPts @0xe3d6685d4e9d8f7a {
|
||||||
|
r @0 :List(UInt16); # uint16 m*500.0
|
||||||
|
theta @1 :List(UInt16); # uint16 deg*100.0
|
||||||
|
reflect @2 :List(UInt8); # uint8 0-255
|
||||||
|
|
||||||
|
# For storing out of file.
|
||||||
|
idx @3 :UInt64;
|
||||||
|
|
||||||
|
# For storing in file
|
||||||
|
pkt @4 :Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LiveTracksDEPRECATED @0xb16f60103159415a {
|
||||||
|
trackId @0 :Int32;
|
||||||
|
dRel @1 :Float32;
|
||||||
|
yRel @2 :Float32;
|
||||||
|
vRel @3 :Float32;
|
||||||
|
aRel @4 :Float32;
|
||||||
|
timeStamp @5 :Float32;
|
||||||
|
status @6 :Float32;
|
||||||
|
currentTime @7 :Float32;
|
||||||
|
stationary @8 :Bool;
|
||||||
|
oncoming @9 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LiveMpcData @0x92a5e332a85f32a0 {
|
||||||
|
x @0 :List(Float32);
|
||||||
|
y @1 :List(Float32);
|
||||||
|
psi @2 :List(Float32);
|
||||||
|
curvature @3 :List(Float32);
|
||||||
|
qpIterations @4 :UInt32;
|
||||||
|
calculationTime @5 :UInt64;
|
||||||
|
cost @6 :Float64;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LiveLongitudinalMpcData @0xe7e17c434f865ae2 {
|
||||||
|
xEgo @0 :List(Float32);
|
||||||
|
vEgo @1 :List(Float32);
|
||||||
|
aEgo @2 :List(Float32);
|
||||||
|
xLead @3 :List(Float32);
|
||||||
|
vLead @4 :List(Float32);
|
||||||
|
aLead @5 :List(Float32);
|
||||||
|
aLeadTau @6 :Float32; # lead accel time constant
|
||||||
|
qpIterations @7 :UInt32;
|
||||||
|
mpcId @8 :UInt32;
|
||||||
|
calculationTime @9 :UInt64;
|
||||||
|
cost @10 :Float64;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DriverStateDEPRECATED @0xb83c6cc593ed0a00 {
|
||||||
|
frameId @0 :UInt32;
|
||||||
|
modelExecutionTime @14 :Float32;
|
||||||
|
dspExecutionTime @16 :Float32;
|
||||||
|
rawPredictions @15 :Data;
|
||||||
|
|
||||||
|
faceOrientation @3 :List(Float32);
|
||||||
|
facePosition @4 :List(Float32);
|
||||||
|
faceProb @5 :Float32;
|
||||||
|
leftEyeProb @6 :Float32;
|
||||||
|
rightEyeProb @7 :Float32;
|
||||||
|
leftBlinkProb @8 :Float32;
|
||||||
|
rightBlinkProb @9 :Float32;
|
||||||
|
faceOrientationStd @11 :List(Float32);
|
||||||
|
facePositionStd @12 :List(Float32);
|
||||||
|
sunglassesProb @13 :Float32;
|
||||||
|
poorVision @17 :Float32;
|
||||||
|
partialFace @18 :Float32;
|
||||||
|
distractedPose @19 :Float32;
|
||||||
|
distractedEyes @20 :Float32;
|
||||||
|
eyesOnRoad @21 :Float32;
|
||||||
|
phoneUse @22 :Float32;
|
||||||
|
occludedProb @23 :Float32;
|
||||||
|
|
||||||
|
readyProb @24 :List(Float32);
|
||||||
|
notReadyProb @25 :List(Float32);
|
||||||
|
|
||||||
|
irPwrDEPRECATED @10 :Float32;
|
||||||
|
descriptorDEPRECATED @1 :List(Float32);
|
||||||
|
stdDEPRECATED @2 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NavModelData @0xac3de5c437be057a {
|
||||||
|
frameId @0 :UInt32;
|
||||||
|
locationMonoTime @6 :UInt64;
|
||||||
|
modelExecutionTime @1 :Float32;
|
||||||
|
dspExecutionTime @2 :Float32;
|
||||||
|
features @3 :List(Float32);
|
||||||
|
# predicted future position
|
||||||
|
position @4 :XYData;
|
||||||
|
desirePrediction @5 :List(Float32);
|
||||||
|
|
||||||
|
# All SI units and in device frame
|
||||||
|
struct XYData @0xbe09e615b2507e26 {
|
||||||
|
x @0 :List(Float32);
|
||||||
|
y @1 :List(Float32);
|
||||||
|
xStd @2 :List(Float32);
|
||||||
|
yStd @3 :List(Float32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AndroidBuildInfo @0xfe2919d5c21f426c {
|
||||||
|
board @0 :Text;
|
||||||
|
bootloader @1 :Text;
|
||||||
|
brand @2 :Text;
|
||||||
|
device @3 :Text;
|
||||||
|
display @4 :Text;
|
||||||
|
fingerprint @5 :Text;
|
||||||
|
hardware @6 :Text;
|
||||||
|
host @7 :Text;
|
||||||
|
id @8 :Text;
|
||||||
|
manufacturer @9 :Text;
|
||||||
|
model @10 :Text;
|
||||||
|
product @11 :Text;
|
||||||
|
radioVersion @12 :Text;
|
||||||
|
serial @13 :Text;
|
||||||
|
supportedAbis @14 :List(Text);
|
||||||
|
tags @15 :Text;
|
||||||
|
time @16 :Int64;
|
||||||
|
type @17 :Text;
|
||||||
|
user @18 :Text;
|
||||||
|
|
||||||
|
versionCodename @19 :Text;
|
||||||
|
versionRelease @20 :Text;
|
||||||
|
versionSdk @21 :Int32;
|
||||||
|
versionSecurityPatch @22 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AndroidSensor @0x9b513b93a887dbcd {
|
||||||
|
id @0 :Int32;
|
||||||
|
name @1 :Text;
|
||||||
|
vendor @2 :Text;
|
||||||
|
version @3 :Int32;
|
||||||
|
handle @4 :Int32;
|
||||||
|
type @5 :Int32;
|
||||||
|
maxRange @6 :Float32;
|
||||||
|
resolution @7 :Float32;
|
||||||
|
power @8 :Float32;
|
||||||
|
minDelay @9 :Int32;
|
||||||
|
fifoReservedEventCount @10 :UInt32;
|
||||||
|
fifoMaxEventCount @11 :UInt32;
|
||||||
|
stringType @12 :Text;
|
||||||
|
maxDelay @13 :Int32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IosBuildInfo @0xd97e3b28239f5580 {
|
||||||
|
appVersion @0 :Text;
|
||||||
|
appBuild @1 :UInt32;
|
||||||
|
osVersion @2 :Text;
|
||||||
|
deviceModel @3 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FrameTypeDEPRECATED @0xa37f0d8558e193fd {
|
||||||
|
unknown @0;
|
||||||
|
neo @1;
|
||||||
|
chffrAndroid @2;
|
||||||
|
front @3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AndroidCaptureResult @0xbcc3efbac41d2048 {
|
||||||
|
sensitivity @0 :Int32;
|
||||||
|
frameDuration @1 :Int64;
|
||||||
|
exposureTime @2 :Int64;
|
||||||
|
rollingShutterSkew @3 :UInt64;
|
||||||
|
colorCorrectionTransform @4 :List(Int32);
|
||||||
|
colorCorrectionGains @5 :List(Float32);
|
||||||
|
displayRotation @6 :Int8;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UsbPowerModeDEPRECATED @0xa8883583b32c9877 {
|
||||||
|
none @0;
|
||||||
|
client @1;
|
||||||
|
cdp @2;
|
||||||
|
dcp @3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LateralINDIState @0x939463348632375e {
|
||||||
|
active @0 :Bool;
|
||||||
|
steeringAngleDeg @1 :Float32;
|
||||||
|
steeringRateDeg @2 :Float32;
|
||||||
|
steeringAccelDeg @3 :Float32;
|
||||||
|
rateSetPoint @4 :Float32;
|
||||||
|
accelSetPoint @5 :Float32;
|
||||||
|
accelError @6 :Float32;
|
||||||
|
delayedOutput @7 :Float32;
|
||||||
|
delta @8 :Float32;
|
||||||
|
output @9 :Float32;
|
||||||
|
saturated @10 :Bool;
|
||||||
|
steeringAngleDesiredDeg @11 :Float32;
|
||||||
|
steeringRateDesiredDeg @12 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LateralLQRState @0x9024e2d790c82ade {
|
||||||
|
active @0 :Bool;
|
||||||
|
steeringAngleDeg @1 :Float32;
|
||||||
|
i @2 :Float32;
|
||||||
|
output @3 :Float32;
|
||||||
|
lqrOutput @4 :Float32;
|
||||||
|
saturated @5 :Bool;
|
||||||
|
steeringAngleDesiredDeg @6 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LateralPlannerSolution @0x84caeca5a6b4acfe {
|
||||||
|
x @0 :List(Float32);
|
||||||
|
y @1 :List(Float32);
|
||||||
|
yaw @2 :List(Float32);
|
||||||
|
yawRate @3 :List(Float32);
|
||||||
|
xStd @4 :List(Float32);
|
||||||
|
yStd @5 :List(Float32);
|
||||||
|
yawStd @6 :List(Float32);
|
||||||
|
yawRateStd @7 :List(Float32);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GpsTrajectory @0x8cfeb072f5301000 {
|
||||||
|
x @0 :List(Float32);
|
||||||
|
y @1 :List(Float32);
|
||||||
|
}
|
||||||
@@ -1,574 +0,0 @@
|
|||||||
using Cxx = import "./include/c++.capnp";
|
|
||||||
$Cxx.namespace("cereal");
|
|
||||||
|
|
||||||
@0x80ef1ec4889c2a63;
|
|
||||||
|
|
||||||
# legacy.capnp: a home for deprecated structs
|
|
||||||
|
|
||||||
struct LogRotate @0x9811e1f38f62f2d1 {
|
|
||||||
segmentNum @0 :Int32;
|
|
||||||
path @1 :Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LiveUI @0xc08240f996aefced {
|
|
||||||
rearViewCam @0 :Bool;
|
|
||||||
alertText1 @1 :Text;
|
|
||||||
alertText2 @2 :Text;
|
|
||||||
awarenessStatus @3 :Float32;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UiLayoutState @0x88dcce08ad29dda0 {
|
|
||||||
activeApp @0 :App;
|
|
||||||
sidebarCollapsed @1 :Bool;
|
|
||||||
mapEnabled @2 :Bool;
|
|
||||||
mockEngaged @3 :Bool;
|
|
||||||
|
|
||||||
enum App @0x9917470acf94d285 {
|
|
||||||
home @0;
|
|
||||||
music @1;
|
|
||||||
nav @2;
|
|
||||||
settings @3;
|
|
||||||
none @4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct OrbslamCorrection @0x8afd33dc9b35e1aa {
|
|
||||||
correctionMonoTime @0 :UInt64;
|
|
||||||
prePositionECEF @1 :List(Float64);
|
|
||||||
postPositionECEF @2 :List(Float64);
|
|
||||||
prePoseQuatECEF @3 :List(Float32);
|
|
||||||
postPoseQuatECEF @4 :List(Float32);
|
|
||||||
numInliers @5 :UInt32;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EthernetPacket @0xa99a9d5b33cf5859 {
|
|
||||||
pkt @0 :Data;
|
|
||||||
ts @1 :Float32;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CellInfo @0xcff7566681c277ce {
|
|
||||||
timestamp @0 :UInt64;
|
|
||||||
repr @1 :Text; # android toString() for now
|
|
||||||
}
|
|
||||||
|
|
||||||
struct WifiScan @0xd4df5a192382ba0b {
|
|
||||||
bssid @0 :Text;
|
|
||||||
ssid @1 :Text;
|
|
||||||
capabilities @2 :Text;
|
|
||||||
frequency @3 :Int32;
|
|
||||||
level @4 :Int32;
|
|
||||||
timestamp @5 :Int64;
|
|
||||||
|
|
||||||
centerFreq0 @6 :Int32;
|
|
||||||
centerFreq1 @7 :Int32;
|
|
||||||
channelWidth @8 :ChannelWidth;
|
|
||||||
operatorFriendlyName @9 :Text;
|
|
||||||
venueName @10 :Text;
|
|
||||||
is80211mcResponder @11 :Bool;
|
|
||||||
passpoint @12 :Bool;
|
|
||||||
|
|
||||||
distanceCm @13 :Int32;
|
|
||||||
distanceSdCm @14 :Int32;
|
|
||||||
|
|
||||||
enum ChannelWidth @0xcb6a279f015f6b51 {
|
|
||||||
w20Mhz @0;
|
|
||||||
w40Mhz @1;
|
|
||||||
w80Mhz @2;
|
|
||||||
w160Mhz @3;
|
|
||||||
w80Plus80Mhz @4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LiveEventData @0x94b7baa90c5c321e {
|
|
||||||
name @0 :Text;
|
|
||||||
value @1 :Int32;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ModelData @0xb8aad62cffef28a9 {
|
|
||||||
frameId @0 :UInt32;
|
|
||||||
frameAge @12 :UInt32;
|
|
||||||
frameDropPerc @13 :Float32;
|
|
||||||
timestampEof @9 :UInt64;
|
|
||||||
modelExecutionTime @14 :Float32;
|
|
||||||
gpuExecutionTime @16 :Float32;
|
|
||||||
rawPred @15 :Data;
|
|
||||||
|
|
||||||
path @1 :PathData;
|
|
||||||
leftLane @2 :PathData;
|
|
||||||
rightLane @3 :PathData;
|
|
||||||
lead @4 :LeadData;
|
|
||||||
freePath @6 :List(Float32);
|
|
||||||
|
|
||||||
settings @5 :ModelSettings;
|
|
||||||
leadFuture @7 :LeadData;
|
|
||||||
speed @8 :List(Float32);
|
|
||||||
meta @10 :MetaData;
|
|
||||||
longitudinal @11 :LongitudinalData;
|
|
||||||
|
|
||||||
struct PathData @0x8817eeea389e9f08 {
|
|
||||||
points @0 :List(Float32);
|
|
||||||
prob @1 :Float32;
|
|
||||||
std @2 :Float32;
|
|
||||||
stds @3 :List(Float32);
|
|
||||||
poly @4 :List(Float32);
|
|
||||||
validLen @5 :Float32;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LeadData @0xd1c9bef96d26fa91 {
|
|
||||||
dist @0 :Float32;
|
|
||||||
prob @1 :Float32;
|
|
||||||
std @2 :Float32;
|
|
||||||
relVel @3 :Float32;
|
|
||||||
relVelStd @4 :Float32;
|
|
||||||
relY @5 :Float32;
|
|
||||||
relYStd @6 :Float32;
|
|
||||||
relA @7 :Float32;
|
|
||||||
relAStd @8 :Float32;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ModelSettings @0xa26e3710efd3e914 {
|
|
||||||
bigBoxX @0 :UInt16;
|
|
||||||
bigBoxY @1 :UInt16;
|
|
||||||
bigBoxWidth @2 :UInt16;
|
|
||||||
bigBoxHeight @3 :UInt16;
|
|
||||||
boxProjection @4 :List(Float32);
|
|
||||||
yuvCorrection @5 :List(Float32);
|
|
||||||
inputTransform @6 :List(Float32);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MetaData @0x9744f25fb60f2bf8 {
|
|
||||||
engagedProb @0 :Float32;
|
|
||||||
desirePrediction @1 :List(Float32);
|
|
||||||
brakeDisengageProb @2 :Float32;
|
|
||||||
gasDisengageProb @3 :Float32;
|
|
||||||
steerOverrideProb @4 :Float32;
|
|
||||||
desireState @5 :List(Float32);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LongitudinalData @0xf98f999c6a071122 {
|
|
||||||
distances @2 :List(Float32);
|
|
||||||
speeds @0 :List(Float32);
|
|
||||||
accelerations @1 :List(Float32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ECEFPoint @0xc25bbbd524983447 {
|
|
||||||
x @0 :Float64;
|
|
||||||
y @1 :Float64;
|
|
||||||
z @2 :Float64;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ECEFPointDEPRECATED @0xe10e21168db0c7f7 {
|
|
||||||
x @0 :Float32;
|
|
||||||
y @1 :Float32;
|
|
||||||
z @2 :Float32;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct GPSPlannerPoints @0xab54c59699f8f9f3 {
|
|
||||||
curPosDEPRECATED @0 :ECEFPointDEPRECATED;
|
|
||||||
pointsDEPRECATED @1 :List(ECEFPointDEPRECATED);
|
|
||||||
curPos @6 :ECEFPoint;
|
|
||||||
points @7 :List(ECEFPoint);
|
|
||||||
valid @2 :Bool;
|
|
||||||
trackName @3 :Text;
|
|
||||||
speedLimit @4 :Float32;
|
|
||||||
accelTarget @5 :Float32;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct GPSPlannerPlan @0xf5ad1d90cdc1dd6b {
|
|
||||||
valid @0 :Bool;
|
|
||||||
poly @1 :List(Float32);
|
|
||||||
trackName @2 :Text;
|
|
||||||
speed @3 :Float32;
|
|
||||||
acceleration @4 :Float32;
|
|
||||||
pointsDEPRECATED @5 :List(ECEFPointDEPRECATED);
|
|
||||||
points @6 :List(ECEFPoint);
|
|
||||||
xLookahead @7 :Float32;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UiNavigationEvent @0x90c8426c3eaddd3b {
|
|
||||||
type @0: Type;
|
|
||||||
status @1: Status;
|
|
||||||
distanceTo @2: Float32;
|
|
||||||
endRoadPointDEPRECATED @3: ECEFPointDEPRECATED;
|
|
||||||
endRoadPoint @4: ECEFPoint;
|
|
||||||
|
|
||||||
enum Type @0xe8db07dcf8fcea05 {
|
|
||||||
none @0;
|
|
||||||
laneChangeLeft @1;
|
|
||||||
laneChangeRight @2;
|
|
||||||
mergeLeft @3;
|
|
||||||
mergeRight @4;
|
|
||||||
turnLeft @5;
|
|
||||||
turnRight @6;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Status @0xb9aa88c75ef99a1f {
|
|
||||||
none @0;
|
|
||||||
passive @1;
|
|
||||||
approaching @2;
|
|
||||||
active @3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LiveLocationData @0xb99b2bc7a57e8128 {
|
|
||||||
status @0 :UInt8;
|
|
||||||
|
|
||||||
# 3D fix
|
|
||||||
lat @1 :Float64;
|
|
||||||
lon @2 :Float64;
|
|
||||||
alt @3 :Float32; # m
|
|
||||||
|
|
||||||
# speed
|
|
||||||
speed @4 :Float32; # m/s
|
|
||||||
|
|
||||||
# NED velocity components
|
|
||||||
vNED @5 :List(Float32);
|
|
||||||
|
|
||||||
# roll, pitch, heading (x,y,z)
|
|
||||||
roll @6 :Float32; # WRT to center of earth?
|
|
||||||
pitch @7 :Float32; # WRT to center of earth?
|
|
||||||
heading @8 :Float32; # WRT to north?
|
|
||||||
|
|
||||||
# what are these?
|
|
||||||
wanderAngle @9 :Float32;
|
|
||||||
trackAngle @10 :Float32;
|
|
||||||
|
|
||||||
# car frame -- https://upload.wikimedia.org/wikipedia/commons/f/f5/RPY_angles_of_cars.png
|
|
||||||
|
|
||||||
# gyro, in car frame, deg/s
|
|
||||||
gyro @11 :List(Float32);
|
|
||||||
|
|
||||||
# accel, in car frame, m/s^2
|
|
||||||
accel @12 :List(Float32);
|
|
||||||
|
|
||||||
accuracy @13 :Accuracy;
|
|
||||||
|
|
||||||
source @14 :SensorSource;
|
|
||||||
# if we are fixing a location in the past
|
|
||||||
fixMonoTime @15 :UInt64;
|
|
||||||
|
|
||||||
gpsWeek @16 :Int32;
|
|
||||||
timeOfWeek @17 :Float64;
|
|
||||||
|
|
||||||
positionECEF @18 :List(Float64);
|
|
||||||
poseQuatECEF @19 :List(Float32);
|
|
||||||
pitchCalibration @20 :Float32;
|
|
||||||
yawCalibration @21 :Float32;
|
|
||||||
imuFrame @22 :List(Float32);
|
|
||||||
|
|
||||||
struct Accuracy @0x943dc4625473b03f {
|
|
||||||
pNEDError @0 :List(Float32);
|
|
||||||
vNEDError @1 :List(Float32);
|
|
||||||
rollError @2 :Float32;
|
|
||||||
pitchError @3 :Float32;
|
|
||||||
headingError @4 :Float32;
|
|
||||||
ellipsoidSemiMajorError @5 :Float32;
|
|
||||||
ellipsoidSemiMinorError @6 :Float32;
|
|
||||||
ellipsoidOrientationError @7 :Float32;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum SensorSource @0xc871d3cc252af657 {
|
|
||||||
applanix @0;
|
|
||||||
kalman @1;
|
|
||||||
orbslam @2;
|
|
||||||
timing @3;
|
|
||||||
dummy @4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct OrbOdometry @0xd7700859ed1f5b76 {
|
|
||||||
# timing first
|
|
||||||
startMonoTime @0 :UInt64;
|
|
||||||
endMonoTime @1 :UInt64;
|
|
||||||
|
|
||||||
# fundamental matrix and error
|
|
||||||
f @2: List(Float64);
|
|
||||||
err @3: Float64;
|
|
||||||
|
|
||||||
# number of inlier points
|
|
||||||
inliers @4: Int32;
|
|
||||||
|
|
||||||
# for debug only
|
|
||||||
# indexed by endMonoTime features
|
|
||||||
# value is startMonoTime feature match
|
|
||||||
# -1 if no match
|
|
||||||
matches @5: List(Int16);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct OrbFeatures @0xcd60164a8a0159ef {
|
|
||||||
timestampEof @0 :UInt64;
|
|
||||||
# transposed arrays of normalized image coordinates
|
|
||||||
# len(xs) == len(ys) == len(descriptors) * 32
|
|
||||||
xs @1 :List(Float32);
|
|
||||||
ys @2 :List(Float32);
|
|
||||||
descriptors @3 :Data;
|
|
||||||
octaves @4 :List(Int8);
|
|
||||||
|
|
||||||
# match index to last OrbFeatures
|
|
||||||
# -1 if no match
|
|
||||||
timestampLastEof @5 :UInt64;
|
|
||||||
matches @6: List(Int16);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct OrbFeaturesSummary @0xd500d30c5803fa4f {
|
|
||||||
timestampEof @0 :UInt64;
|
|
||||||
timestampLastEof @1 :UInt64;
|
|
||||||
|
|
||||||
featureCount @2 :UInt16;
|
|
||||||
matchCount @3 :UInt16;
|
|
||||||
computeNs @4 :UInt64;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct OrbKeyFrame @0xc8233c0345e27e24 {
|
|
||||||
# this is a globally unique id for the KeyFrame
|
|
||||||
id @0: UInt64;
|
|
||||||
|
|
||||||
# this is the location of the KeyFrame
|
|
||||||
pos @1: ECEFPoint;
|
|
||||||
|
|
||||||
# these are the features in the world
|
|
||||||
# len(dpos) == len(descriptors) * 32
|
|
||||||
dpos @2 :List(ECEFPoint);
|
|
||||||
descriptors @3 :Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct KalmanOdometry @0x92e21bb7ea38793a {
|
|
||||||
trans @0 :List(Float32); # m/s in device frame
|
|
||||||
rot @1 :List(Float32); # rad/s in device frame
|
|
||||||
transStd @2 :List(Float32); # std m/s in device frame
|
|
||||||
rotStd @3 :List(Float32); # std rad/s in device frame
|
|
||||||
}
|
|
||||||
|
|
||||||
struct OrbObservation @0x9b326d4e436afec7 {
|
|
||||||
observationMonoTime @0 :UInt64;
|
|
||||||
normalizedCoordinates @1 :List(Float32);
|
|
||||||
locationECEF @2 :List(Float64);
|
|
||||||
matchDistance @3: UInt32;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CalibrationFeatures @0x8fdfadb254ea867a {
|
|
||||||
frameId @0 :UInt32;
|
|
||||||
|
|
||||||
p0 @1 :List(Float32);
|
|
||||||
p1 @2 :List(Float32);
|
|
||||||
status @3 :List(Int8);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NavStatus @0xbd8822120928120c {
|
|
||||||
isNavigating @0 :Bool;
|
|
||||||
currentAddress @1 :Address;
|
|
||||||
|
|
||||||
struct Address @0xce7cd672cacc7814 {
|
|
||||||
title @0 :Text;
|
|
||||||
lat @1 :Float64;
|
|
||||||
lng @2 :Float64;
|
|
||||||
house @3 :Text;
|
|
||||||
address @4 :Text;
|
|
||||||
street @5 :Text;
|
|
||||||
city @6 :Text;
|
|
||||||
state @7 :Text;
|
|
||||||
country @8 :Text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NavUpdate @0xdb98be6565516acb {
|
|
||||||
isNavigating @0 :Bool;
|
|
||||||
curSegment @1 :Int32;
|
|
||||||
segments @2 :List(Segment);
|
|
||||||
|
|
||||||
struct LatLng @0x9eaef9187cadbb9b {
|
|
||||||
lat @0 :Float64;
|
|
||||||
lng @1 :Float64;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Segment @0xa5b39b4fc4d7da3f {
|
|
||||||
from @0 :LatLng;
|
|
||||||
to @1 :LatLng;
|
|
||||||
updateTime @2 :Int32;
|
|
||||||
distance @3 :Int32;
|
|
||||||
crossTime @4 :Int32;
|
|
||||||
exitNo @5 :Int32;
|
|
||||||
instruction @6 :Instruction;
|
|
||||||
|
|
||||||
parts @7 :List(LatLng);
|
|
||||||
|
|
||||||
enum Instruction @0xc5417a637451246f {
|
|
||||||
turnLeft @0;
|
|
||||||
turnRight @1;
|
|
||||||
keepLeft @2;
|
|
||||||
keepRight @3;
|
|
||||||
straight @4;
|
|
||||||
roundaboutExitNumber @5;
|
|
||||||
roundaboutExit @6;
|
|
||||||
roundaboutTurnLeft @7;
|
|
||||||
unkn8 @8;
|
|
||||||
roundaboutStraight @9;
|
|
||||||
unkn10 @10;
|
|
||||||
roundaboutTurnRight @11;
|
|
||||||
unkn12 @12;
|
|
||||||
roundaboutUturn @13;
|
|
||||||
unkn14 @14;
|
|
||||||
arrive @15;
|
|
||||||
exitLeft @16;
|
|
||||||
exitRight @17;
|
|
||||||
unkn18 @18;
|
|
||||||
uturn @19;
|
|
||||||
# ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TrafficEvent @0xacfa74a094e62626 {
|
|
||||||
type @0 :Type;
|
|
||||||
distance @1 :Float32;
|
|
||||||
action @2 :Action;
|
|
||||||
resuming @3 :Bool;
|
|
||||||
|
|
||||||
enum Type @0xd85d75253435bf4b {
|
|
||||||
stopSign @0;
|
|
||||||
lightRed @1;
|
|
||||||
lightYellow @2;
|
|
||||||
lightGreen @3;
|
|
||||||
stopLight @4;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Action @0xa6f6ce72165ccb49 {
|
|
||||||
none @0;
|
|
||||||
yield @1;
|
|
||||||
stop @2;
|
|
||||||
resumeReady @3;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct AndroidGnss @0xdfdf30d03fc485bd {
|
|
||||||
union {
|
|
||||||
measurements @0 :Measurements;
|
|
||||||
navigationMessage @1 :NavigationMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Measurements @0xa20710d4f428d6cd {
|
|
||||||
clock @0 :Clock;
|
|
||||||
measurements @1 :List(Measurement);
|
|
||||||
|
|
||||||
struct Clock @0xa0e27b453a38f450 {
|
|
||||||
timeNanos @0 :Int64;
|
|
||||||
hardwareClockDiscontinuityCount @1 :Int32;
|
|
||||||
|
|
||||||
hasTimeUncertaintyNanos @2 :Bool;
|
|
||||||
timeUncertaintyNanos @3 :Float64;
|
|
||||||
|
|
||||||
hasLeapSecond @4 :Bool;
|
|
||||||
leapSecond @5 :Int32;
|
|
||||||
|
|
||||||
hasFullBiasNanos @6 :Bool;
|
|
||||||
fullBiasNanos @7 :Int64;
|
|
||||||
|
|
||||||
hasBiasNanos @8 :Bool;
|
|
||||||
biasNanos @9 :Float64;
|
|
||||||
|
|
||||||
hasBiasUncertaintyNanos @10 :Bool;
|
|
||||||
biasUncertaintyNanos @11 :Float64;
|
|
||||||
|
|
||||||
hasDriftNanosPerSecond @12 :Bool;
|
|
||||||
driftNanosPerSecond @13 :Float64;
|
|
||||||
|
|
||||||
hasDriftUncertaintyNanosPerSecond @14 :Bool;
|
|
||||||
driftUncertaintyNanosPerSecond @15 :Float64;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Measurement @0xd949bf717d77614d {
|
|
||||||
svId @0 :Int32;
|
|
||||||
constellation @1 :Constellation;
|
|
||||||
|
|
||||||
timeOffsetNanos @2 :Float64;
|
|
||||||
state @3 :Int32;
|
|
||||||
receivedSvTimeNanos @4 :Int64;
|
|
||||||
receivedSvTimeUncertaintyNanos @5 :Int64;
|
|
||||||
cn0DbHz @6 :Float64;
|
|
||||||
pseudorangeRateMetersPerSecond @7 :Float64;
|
|
||||||
pseudorangeRateUncertaintyMetersPerSecond @8 :Float64;
|
|
||||||
accumulatedDeltaRangeState @9 :Int32;
|
|
||||||
accumulatedDeltaRangeMeters @10 :Float64;
|
|
||||||
accumulatedDeltaRangeUncertaintyMeters @11 :Float64;
|
|
||||||
|
|
||||||
hasCarrierFrequencyHz @12 :Bool;
|
|
||||||
carrierFrequencyHz @13 :Float32;
|
|
||||||
hasCarrierCycles @14 :Bool;
|
|
||||||
carrierCycles @15 :Int64;
|
|
||||||
hasCarrierPhase @16 :Bool;
|
|
||||||
carrierPhase @17 :Float64;
|
|
||||||
hasCarrierPhaseUncertainty @18 :Bool;
|
|
||||||
carrierPhaseUncertainty @19 :Float64;
|
|
||||||
hasSnrInDb @20 :Bool;
|
|
||||||
snrInDb @21 :Float64;
|
|
||||||
|
|
||||||
multipathIndicator @22 :MultipathIndicator;
|
|
||||||
|
|
||||||
enum Constellation @0x9ef1f3ff0deb5ffb {
|
|
||||||
unknown @0;
|
|
||||||
gps @1;
|
|
||||||
sbas @2;
|
|
||||||
glonass @3;
|
|
||||||
qzss @4;
|
|
||||||
beidou @5;
|
|
||||||
galileo @6;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum State @0xcbb9490adce12d72 {
|
|
||||||
unknown @0;
|
|
||||||
codeLock @1;
|
|
||||||
bitSync @2;
|
|
||||||
subframeSync @3;
|
|
||||||
towDecoded @4;
|
|
||||||
msecAmbiguous @5;
|
|
||||||
symbolSync @6;
|
|
||||||
gloStringSync @7;
|
|
||||||
gloTodDecoded @8;
|
|
||||||
bdsD2BitSync @9;
|
|
||||||
bdsD2SubframeSync @10;
|
|
||||||
galE1bcCodeLock @11;
|
|
||||||
galE1c2ndCodeLock @12;
|
|
||||||
galE1bPageSync @13;
|
|
||||||
sbasSync @14;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum MultipathIndicator @0xc04e7b6231d4caa8 {
|
|
||||||
unknown @0;
|
|
||||||
detected @1;
|
|
||||||
notDetected @2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NavigationMessage @0xe2517b083095fd4e {
|
|
||||||
type @0 :Int32;
|
|
||||||
svId @1 :Int32;
|
|
||||||
messageId @2 :Int32;
|
|
||||||
submessageId @3 :Int32;
|
|
||||||
data @4 :Data;
|
|
||||||
status @5 :Status;
|
|
||||||
|
|
||||||
enum Status @0xec1ff7996b35366f {
|
|
||||||
unknown @0;
|
|
||||||
parityPassed @1;
|
|
||||||
parityRebuilt @2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LidarPts @0xe3d6685d4e9d8f7a {
|
|
||||||
r @0 :List(UInt16); # uint16 m*500.0
|
|
||||||
theta @1 :List(UInt16); # uint16 deg*100.0
|
|
||||||
reflect @2 :List(UInt8); # uint8 0-255
|
|
||||||
|
|
||||||
# For storing out of file.
|
|
||||||
idx @3 :UInt64;
|
|
||||||
|
|
||||||
# For storing in file
|
|
||||||
pkt @4 :Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
+457
-560
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,8 @@
|
|||||||
# must be built with scons
|
# must be built with scons
|
||||||
from msgq.ipc_pyx import Context, Poller, SubSocket, PubSocket, SocketEventHandle, toggle_fake_events, \
|
from msgq import fake_event_handle, drain_sock_raw, MultiplePublishersError, IpcError, \
|
||||||
set_fake_prefix, get_fake_prefix, delete_fake_prefix, wait_for_one_event
|
Context, Poller, SubSocket, PubSocket, SocketEventHandle, toggle_fake_events, \
|
||||||
from msgq.ipc_pyx import MultiplePublishersError, IpcError
|
set_fake_prefix, get_fake_prefix, delete_fake_prefix, wait_for_one_event
|
||||||
from msgq import fake_event_handle, pub_sock, sub_sock, drain_sock_raw
|
|
||||||
import msgq
|
import msgq
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import capnp
|
import capnp
|
||||||
import time
|
import time
|
||||||
@@ -13,11 +11,25 @@ from typing import Optional, List, Union, Dict
|
|||||||
|
|
||||||
from cereal import log
|
from cereal import log
|
||||||
from cereal.services import SERVICE_LIST
|
from cereal.services import SERVICE_LIST
|
||||||
from openpilot.common.util import MovingAverage
|
from openpilot.common.utils import MovingAverage
|
||||||
|
|
||||||
NO_TRAVERSAL_LIMIT = 2**64-1
|
NO_TRAVERSAL_LIMIT = 2**64-1
|
||||||
|
|
||||||
|
|
||||||
|
def pub_sock(endpoint: str) -> PubSocket:
|
||||||
|
service = SERVICE_LIST.get(endpoint)
|
||||||
|
segment_size = service.queue_size if service else 0
|
||||||
|
return msgq.pub_sock(endpoint, segment_size)
|
||||||
|
|
||||||
|
|
||||||
|
def sub_sock(endpoint: str, poller: Optional[Poller] = None, addr: str = "127.0.0.1",
|
||||||
|
conflate: bool = False, timeout: Optional[int] = None) -> SubSocket:
|
||||||
|
service = SERVICE_LIST.get(endpoint)
|
||||||
|
segment_size = service.queue_size if service else 0
|
||||||
|
return msgq.sub_sock(endpoint, poller=poller, addr=addr, conflate=conflate,
|
||||||
|
timeout=timeout, segment_size=segment_size)
|
||||||
|
|
||||||
|
|
||||||
def reset_context():
|
def reset_context():
|
||||||
msgq.context = Context()
|
msgq.context = Context()
|
||||||
|
|
||||||
@@ -247,11 +259,11 @@ class PubMaster:
|
|||||||
self.sock[s].send(dat)
|
self.sock[s].send(dat)
|
||||||
|
|
||||||
def wait_for_readers_to_update(self, s: str, timeout: int, dt: float = 0.05) -> bool:
|
def wait_for_readers_to_update(self, s: str, timeout: int, dt: float = 0.05) -> bool:
|
||||||
for _ in range(int(timeout*(1./dt))):
|
try:
|
||||||
if self.sock[s].all_readers_updated():
|
self.sock[s].wait_for_readers(timeout=timeout, interval=dt)
|
||||||
return True
|
return True
|
||||||
time.sleep(dt)
|
except TimeoutError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def all_readers_updated(self, s: str) -> bool:
|
def all_readers_updated(self, s: str) -> bool:
|
||||||
return self.sock[s].all_readers_updated() # type: ignore
|
return self.sock[s].all_readers_updated()
|
||||||
|
|||||||
+17
-47
@@ -1,7 +1,4 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <unordered_set>
|
|
||||||
#include <sstream>
|
|
||||||
#include <cctype>
|
|
||||||
|
|
||||||
#include "cereal/messaging/msgq_to_zmq.h"
|
#include "cereal/messaging/msgq_to_zmq.h"
|
||||||
#include "cereal/services.h"
|
#include "cereal/services.h"
|
||||||
@@ -9,62 +6,35 @@
|
|||||||
|
|
||||||
ExitHandler do_exit;
|
ExitHandler do_exit;
|
||||||
|
|
||||||
static std::unordered_set<std::string> parse_whitelist(const std::string& s) {
|
static std::vector<std::string> get_services(const std::string &whitelist_str, bool zmq_to_msgq) {
|
||||||
std::unordered_set<std::string> out;
|
|
||||||
std::string token;
|
|
||||||
token.reserve(s.size());
|
|
||||||
|
|
||||||
auto flush = [&]() {
|
|
||||||
if (!token.empty()) {
|
|
||||||
out.insert(token);
|
|
||||||
token.clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (char c : s) {
|
|
||||||
// 구분자: 콤마/공백/탭/세미콜론/파이프 등
|
|
||||||
if (std::isspace((unsigned char)c) || c == ',' || c == ';' || c == '|') {
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
token.push_back(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
flush();
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::vector<std::string> get_services(const std::string& whitelist_str, bool /*zmq_to_msgq*/) {
|
|
||||||
std::vector<std::string> service_list;
|
std::vector<std::string> service_list;
|
||||||
|
|
||||||
const bool use_filter = !whitelist_str.empty();
|
|
||||||
std::unordered_set<std::string> whitelist = use_filter ? parse_whitelist(whitelist_str)
|
|
||||||
: std::unordered_set<std::string>{};
|
|
||||||
|
|
||||||
for (const auto& it : services) {
|
for (const auto& it : services) {
|
||||||
const std::string& name = it.second.name;
|
std::string name = it.second.name;
|
||||||
if (use_filter && whitelist.find(name) == whitelist.end()) continue;
|
bool in_whitelist = whitelist_str.find(name) != std::string::npos;
|
||||||
|
if (zmq_to_msgq && !in_whitelist) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
service_list.push_back(name);
|
service_list.push_back(name);
|
||||||
}
|
}
|
||||||
return service_list;
|
return service_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void msgq_to_zmq(const std::vector<std::string> &endpoints, const std::string &ip) {
|
void msgq_to_zmq(const std::vector<std::string> &endpoints, const std::string &ip) {
|
||||||
MsgqToZmq bridge;
|
MsgqToZmq bridge;
|
||||||
bridge.run(endpoints, ip);
|
bridge.run(endpoints, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void zmq_to_msgq(const std::vector<std::string> &endpoints, const std::string &ip) {
|
void zmq_to_msgq(const std::vector<std::string> &endpoints, const std::string &ip) {
|
||||||
auto poller = std::make_unique<ZMQPoller>();
|
auto poller = std::make_unique<BridgeZmqPoller>();
|
||||||
auto pub_context = std::make_unique<MSGQContext>();
|
auto pub_context = std::make_unique<Context>();
|
||||||
auto sub_context = std::make_unique<ZMQContext>();
|
auto sub_context = std::make_unique<BridgeZmqContext>();
|
||||||
std::map<SubSocket *, PubSocket *> sub2pub;
|
std::map<BridgeZmqSubSocket *, PubSocket *> sub2pub;
|
||||||
|
|
||||||
for (auto endpoint : endpoints) {
|
for (auto endpoint : endpoints) {
|
||||||
auto pub_sock = new MSGQPubSocket();
|
auto pub_sock = new PubSocket();
|
||||||
auto sub_sock = new ZMQSubSocket();
|
auto sub_sock = new BridgeZmqSubSocket();
|
||||||
pub_sock->connect(pub_context.get(), endpoint);
|
size_t queue_size = services.at(endpoint).queue_size;
|
||||||
|
pub_sock->connect(pub_context.get(), endpoint, true, queue_size);
|
||||||
sub_sock->connect(sub_context.get(), endpoint, ip, false);
|
sub_sock->connect(sub_context.get(), endpoint, ip, false);
|
||||||
|
|
||||||
poller->registerSocket(sub_sock);
|
poller->registerSocket(sub_sock);
|
||||||
@@ -88,9 +58,9 @@ void zmq_to_msgq(const std::vector<std::string> &endpoints, const std::string &i
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
bool is_zmq_to_msgq = argc > 3;
|
bool is_zmq_to_msgq = argc > 2;
|
||||||
std::string ip = argc > 2 ? argv[1] : "127.0.0.1";
|
std::string ip = is_zmq_to_msgq ? argv[1] : "127.0.0.1";
|
||||||
std::string whitelist_str = argc > 2 ? std::string(argv[2]) : "";
|
std::string whitelist_str = is_zmq_to_msgq ? std::string(argv[2]) : "";
|
||||||
std::vector<std::string> endpoints = get_services(whitelist_str, is_zmq_to_msgq);
|
std::vector<std::string> endpoints = get_services(whitelist_str, is_zmq_to_msgq);
|
||||||
|
|
||||||
if (is_zmq_to_msgq) {
|
if (is_zmq_to_msgq) {
|
||||||
|
|||||||
@@ -0,0 +1,170 @@
|
|||||||
|
#include "cereal/messaging/bridge_zmq.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static size_t fnv1a_hash(const std::string &str) {
|
||||||
|
const size_t fnv_prime = 0x100000001b3;
|
||||||
|
size_t hash_value = 0xcbf29ce484222325;
|
||||||
|
for (char c : str) {
|
||||||
|
hash_value ^= (unsigned char)c;
|
||||||
|
hash_value *= fnv_prime;
|
||||||
|
}
|
||||||
|
return hash_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: This is a hack to get the port number from the socket name, might have collisions.
|
||||||
|
static int get_port(std::string endpoint) {
|
||||||
|
size_t hash_value = fnv1a_hash(endpoint);
|
||||||
|
int start_port = 8023;
|
||||||
|
int max_port = 65535;
|
||||||
|
return start_port + (hash_value % (max_port - start_port));
|
||||||
|
}
|
||||||
|
|
||||||
|
BridgeZmqContext::BridgeZmqContext() {
|
||||||
|
context = zmq_ctx_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
BridgeZmqContext::~BridgeZmqContext() {
|
||||||
|
if (context != nullptr) {
|
||||||
|
zmq_ctx_term(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BridgeZmqMessage::init(size_t sz) {
|
||||||
|
size = sz;
|
||||||
|
data = new char[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
void BridgeZmqMessage::init(char *d, size_t sz) {
|
||||||
|
size = sz;
|
||||||
|
data = new char[size];
|
||||||
|
memcpy(data, d, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BridgeZmqMessage::close() {
|
||||||
|
if (size > 0) {
|
||||||
|
delete[] data;
|
||||||
|
}
|
||||||
|
data = nullptr;
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BridgeZmqMessage::~BridgeZmqMessage() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int BridgeZmqSubSocket::connect(BridgeZmqContext *context, std::string endpoint, std::string address, bool conflate, bool check_endpoint) {
|
||||||
|
sock = zmq_socket(context->getRawContext(), ZMQ_SUB);
|
||||||
|
if (sock == nullptr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
zmq_setsockopt(sock, ZMQ_SUBSCRIBE, "", 0);
|
||||||
|
|
||||||
|
if (conflate) {
|
||||||
|
int arg = 1;
|
||||||
|
zmq_setsockopt(sock, ZMQ_CONFLATE, &arg, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
int reconnect_ivl = 500;
|
||||||
|
zmq_setsockopt(sock, ZMQ_RECONNECT_IVL_MAX, &reconnect_ivl, sizeof(reconnect_ivl));
|
||||||
|
|
||||||
|
full_endpoint = "tcp://" + address + ":";
|
||||||
|
if (check_endpoint) {
|
||||||
|
full_endpoint += std::to_string(get_port(endpoint));
|
||||||
|
} else {
|
||||||
|
full_endpoint += endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
return zmq_connect(sock, full_endpoint.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void BridgeZmqSubSocket::setTimeout(int timeout) {
|
||||||
|
zmq_setsockopt(sock, ZMQ_RCVTIMEO, &timeout, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
Message *BridgeZmqSubSocket::receive(bool non_blocking) {
|
||||||
|
zmq_msg_t msg;
|
||||||
|
assert(zmq_msg_init(&msg) == 0);
|
||||||
|
|
||||||
|
int flags = non_blocking ? ZMQ_DONTWAIT : 0;
|
||||||
|
int rc = zmq_msg_recv(&msg, sock, flags);
|
||||||
|
|
||||||
|
Message *ret = nullptr;
|
||||||
|
if (rc >= 0) {
|
||||||
|
ret = new BridgeZmqMessage;
|
||||||
|
ret->init((char *)zmq_msg_data(&msg), zmq_msg_size(&msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
zmq_msg_close(&msg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
BridgeZmqSubSocket::~BridgeZmqSubSocket() {
|
||||||
|
if (sock != nullptr) {
|
||||||
|
zmq_close(sock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int BridgeZmqPubSocket::connect(BridgeZmqContext *context, std::string endpoint, bool check_endpoint) {
|
||||||
|
sock = zmq_socket(context->getRawContext(), ZMQ_PUB);
|
||||||
|
if (sock == nullptr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
full_endpoint = "tcp://*:";
|
||||||
|
if (check_endpoint) {
|
||||||
|
full_endpoint += std::to_string(get_port(endpoint));
|
||||||
|
} else {
|
||||||
|
full_endpoint += endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZMQ pub sockets cannot be shared between processes, so we need to ensure pid stays the same.
|
||||||
|
pid = getpid();
|
||||||
|
|
||||||
|
return zmq_bind(sock, full_endpoint.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
int BridgeZmqPubSocket::sendMessage(Message *message) {
|
||||||
|
assert(pid == getpid());
|
||||||
|
return zmq_send(sock, message->getData(), message->getSize(), ZMQ_DONTWAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BridgeZmqPubSocket::send(char *data, size_t size) {
|
||||||
|
assert(pid == getpid());
|
||||||
|
return zmq_send(sock, data, size, ZMQ_DONTWAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
BridgeZmqPubSocket::~BridgeZmqPubSocket() {
|
||||||
|
if (sock != nullptr) {
|
||||||
|
zmq_close(sock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BridgeZmqPoller::registerSocket(BridgeZmqSubSocket *socket) {
|
||||||
|
assert(num_polls + 1 < (sizeof(polls) / sizeof(polls[0])));
|
||||||
|
polls[num_polls].socket = socket->getRawSocket();
|
||||||
|
polls[num_polls].events = ZMQ_POLLIN;
|
||||||
|
|
||||||
|
sockets.push_back(socket);
|
||||||
|
num_polls++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<BridgeZmqSubSocket *> BridgeZmqPoller::poll(int timeout) {
|
||||||
|
std::vector<BridgeZmqSubSocket *> ret;
|
||||||
|
|
||||||
|
int rc = zmq_poll(polls, num_polls, timeout);
|
||||||
|
if (rc < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_polls; i++) {
|
||||||
|
if (polls[i].revents) {
|
||||||
|
ret.push_back(sockets[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <zmq.h>
|
||||||
|
|
||||||
|
#include "msgq/ipc.h"
|
||||||
|
|
||||||
|
class BridgeZmqContext {
|
||||||
|
public:
|
||||||
|
BridgeZmqContext();
|
||||||
|
void *getRawContext() { return context; }
|
||||||
|
~BridgeZmqContext();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *context = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BridgeZmqMessage : public Message {
|
||||||
|
public:
|
||||||
|
void init(size_t size);
|
||||||
|
void init(char *data, size_t size);
|
||||||
|
void close();
|
||||||
|
size_t getSize() { return size; }
|
||||||
|
char *getData() { return data; }
|
||||||
|
~BridgeZmqMessage();
|
||||||
|
|
||||||
|
private:
|
||||||
|
char *data = nullptr;
|
||||||
|
size_t size = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BridgeZmqSubSocket {
|
||||||
|
public:
|
||||||
|
int connect(BridgeZmqContext *context, std::string endpoint, std::string address, bool conflate = false, bool check_endpoint = true);
|
||||||
|
void setTimeout(int timeout);
|
||||||
|
Message *receive(bool non_blocking = false);
|
||||||
|
void *getRawSocket() { return sock; }
|
||||||
|
~BridgeZmqSubSocket();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *sock = nullptr;
|
||||||
|
std::string full_endpoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BridgeZmqPubSocket {
|
||||||
|
public:
|
||||||
|
int connect(BridgeZmqContext *context, std::string endpoint, bool check_endpoint = true);
|
||||||
|
int sendMessage(Message *message);
|
||||||
|
int send(char *data, size_t size);
|
||||||
|
void *getRawSocket() { return sock; }
|
||||||
|
~BridgeZmqPubSocket();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *sock = nullptr;
|
||||||
|
std::string full_endpoint;
|
||||||
|
int pid = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BridgeZmqPoller {
|
||||||
|
public:
|
||||||
|
void registerSocket(BridgeZmqSubSocket *socket);
|
||||||
|
std::vector<BridgeZmqSubSocket *> poll(int timeout);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr size_t MAX_BRIDGE_ZMQ_POLLERS = 128;
|
||||||
|
std::vector<BridgeZmqSubSocket *> sockets;
|
||||||
|
zmq_pollitem_t polls[MAX_BRIDGE_ZMQ_POLLERS] = {};
|
||||||
|
size_t num_polls = 0;
|
||||||
|
};
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "cereal/services.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
||||||
extern ExitHandler do_exit;
|
extern ExitHandler do_exit;
|
||||||
@@ -21,14 +22,14 @@ static std::string recv_zmq_msg(void *sock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MsgqToZmq::run(const std::vector<std::string> &endpoints, const std::string &ip) {
|
void MsgqToZmq::run(const std::vector<std::string> &endpoints, const std::string &ip) {
|
||||||
zmq_context = std::make_unique<ZMQContext>();
|
zmq_context = std::make_unique<BridgeZmqContext>();
|
||||||
msgq_context = std::make_unique<MSGQContext>();
|
msgq_context = std::make_unique<Context>();
|
||||||
|
|
||||||
// Create ZMQPubSockets for each endpoint
|
// Create ZMQPubSockets for each endpoint
|
||||||
for (const auto &endpoint : endpoints) {
|
for (const auto &endpoint : endpoints) {
|
||||||
auto &socket_pair = socket_pairs.emplace_back();
|
auto &socket_pair = socket_pairs.emplace_back();
|
||||||
socket_pair.endpoint = endpoint;
|
socket_pair.endpoint = endpoint;
|
||||||
socket_pair.pub_sock = std::make_unique<ZMQPubSocket>();
|
socket_pair.pub_sock = std::make_unique<BridgeZmqPubSocket>();
|
||||||
int ret = socket_pair.pub_sock->connect(zmq_context.get(), endpoint);
|
int ret = socket_pair.pub_sock->connect(zmq_context.get(), endpoint);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
printf("Failed to create ZMQ publisher for [%s]: %s\n", endpoint.c_str(), zmq_strerror(zmq_errno()));
|
printf("Failed to create ZMQ publisher for [%s]: %s\n", endpoint.c_str(), zmq_strerror(zmq_errno()));
|
||||||
@@ -48,7 +49,7 @@ void MsgqToZmq::run(const std::vector<std::string> &endpoints, const std::string
|
|||||||
|
|
||||||
for (auto sub_sock : msgq_poller->poll(100)) {
|
for (auto sub_sock : msgq_poller->poll(100)) {
|
||||||
// Process messages for each socket
|
// Process messages for each socket
|
||||||
ZMQPubSocket *pub_sock = sub2pub.at(sub_sock);
|
BridgeZmqPubSocket *pub_sock = sub2pub.at(sub_sock);
|
||||||
for (int i = 0; i < MAX_MESSAGES_PER_SOCKET; ++i) {
|
for (int i = 0; i < MAX_MESSAGES_PER_SOCKET; ++i) {
|
||||||
auto msg = std::unique_ptr<Message>(sub_sock->receive(true));
|
auto msg = std::unique_ptr<Message>(sub_sock->receive(true));
|
||||||
if (!msg) break;
|
if (!msg) break;
|
||||||
@@ -71,7 +72,7 @@ void MsgqToZmq::zmqMonitorThread() {
|
|||||||
// Set up ZMQ monitor for each pub socket
|
// Set up ZMQ monitor for each pub socket
|
||||||
for (int i = 0; i < socket_pairs.size(); ++i) {
|
for (int i = 0; i < socket_pairs.size(); ++i) {
|
||||||
std::string addr = "inproc://op-bridge-monitor-" + std::to_string(i);
|
std::string addr = "inproc://op-bridge-monitor-" + std::to_string(i);
|
||||||
zmq_socket_monitor(socket_pairs[i].pub_sock->sock, addr.c_str(), ZMQ_EVENT_ACCEPTED | ZMQ_EVENT_DISCONNECTED);
|
zmq_socket_monitor(socket_pairs[i].pub_sock->getRawSocket(), addr.c_str(), ZMQ_EVENT_ACCEPTED | ZMQ_EVENT_DISCONNECTED);
|
||||||
|
|
||||||
void *monitor_socket = zmq_socket(zmq_context->getRawContext(), ZMQ_PAIR);
|
void *monitor_socket = zmq_socket(zmq_context->getRawContext(), ZMQ_PAIR);
|
||||||
zmq_connect(monitor_socket, addr.c_str());
|
zmq_connect(monitor_socket, addr.c_str());
|
||||||
@@ -108,7 +109,8 @@ void MsgqToZmq::zmqMonitorThread() {
|
|||||||
if (++pair.connected_clients == 1) {
|
if (++pair.connected_clients == 1) {
|
||||||
// Create new MSGQ subscriber socket and map to ZMQ publisher
|
// Create new MSGQ subscriber socket and map to ZMQ publisher
|
||||||
pair.sub_sock = std::make_unique<MSGQSubSocket>();
|
pair.sub_sock = std::make_unique<MSGQSubSocket>();
|
||||||
pair.sub_sock->connect(msgq_context.get(), pair.endpoint, "127.0.0.1");
|
size_t queue_size = services.at(pair.endpoint).queue_size;
|
||||||
|
pair.sub_sock->connect(msgq_context.get(), pair.endpoint, "127.0.0.1", false, true, queue_size);
|
||||||
sub2pub[pair.sub_sock.get()] = pair.pub_sock.get();
|
sub2pub[pair.sub_sock.get()] = pair.pub_sock.get();
|
||||||
registerSockets();
|
registerSockets();
|
||||||
}
|
}
|
||||||
@@ -128,7 +130,7 @@ void MsgqToZmq::zmqMonitorThread() {
|
|||||||
|
|
||||||
// Clean up monitor sockets
|
// Clean up monitor sockets
|
||||||
for (int i = 0; i < pollitems.size(); ++i) {
|
for (int i = 0; i < pollitems.size(); ++i) {
|
||||||
zmq_socket_monitor(socket_pairs[i].pub_sock->sock, nullptr, 0);
|
zmq_socket_monitor(socket_pairs[i].pub_sock->getRawSocket(), nullptr, 0);
|
||||||
zmq_close(pollitems[i].socket);
|
zmq_close(pollitems[i].socket);
|
||||||
}
|
}
|
||||||
cv.notify_one();
|
cv.notify_one();
|
||||||
|
|||||||
@@ -7,9 +7,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#define private public
|
|
||||||
#include "msgq/impl_msgq.h"
|
#include "msgq/impl_msgq.h"
|
||||||
#include "msgq/impl_zmq.h"
|
#include "cereal/messaging/bridge_zmq.h"
|
||||||
|
|
||||||
class MsgqToZmq {
|
class MsgqToZmq {
|
||||||
public:
|
public:
|
||||||
@@ -22,16 +21,16 @@ protected:
|
|||||||
|
|
||||||
struct SocketPair {
|
struct SocketPair {
|
||||||
std::string endpoint;
|
std::string endpoint;
|
||||||
std::unique_ptr<ZMQPubSocket> pub_sock;
|
std::unique_ptr<BridgeZmqPubSocket> pub_sock;
|
||||||
std::unique_ptr<MSGQSubSocket> sub_sock;
|
std::unique_ptr<MSGQSubSocket> sub_sock;
|
||||||
int connected_clients = 0;
|
int connected_clients = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<MSGQContext> msgq_context;
|
std::unique_ptr<Context> msgq_context;
|
||||||
std::unique_ptr<ZMQContext> zmq_context;
|
std::unique_ptr<BridgeZmqContext> zmq_context;
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
std::unique_ptr<MSGQPoller> msgq_poller;
|
std::unique_ptr<MSGQPoller> msgq_poller;
|
||||||
std::map<SubSocket *, ZMQPubSocket *> sub2pub;
|
std::map<SubSocket *, BridgeZmqPubSocket *> sub2pub;
|
||||||
std::vector<SocketPair> socket_pairs;
|
std::vector<SocketPair> socket_pairs;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ MessageContext message_context;
|
|||||||
struct SubMaster::SubMessage {
|
struct SubMaster::SubMessage {
|
||||||
std::string name;
|
std::string name;
|
||||||
SubSocket *socket = nullptr;
|
SubSocket *socket = nullptr;
|
||||||
int freq = 0;
|
float freq = 0.0f;
|
||||||
bool updated = false, alive = false, valid = false, ignore_alive;
|
bool updated = false, alive = false, valid = false, ignore_alive;
|
||||||
uint64_t rcv_time = 0, rcv_frame = 0;
|
uint64_t rcv_time = 0, rcv_frame = 0;
|
||||||
void *allocated_msg_reader = nullptr;
|
void *allocated_msg_reader = nullptr;
|
||||||
@@ -47,13 +47,10 @@ SubMaster::SubMaster(const std::vector<const char *> &service_list, const std::v
|
|||||||
const char *address, const std::vector<const char *> &ignore_alive) {
|
const char *address, const std::vector<const char *> &ignore_alive) {
|
||||||
poller_ = Poller::create();
|
poller_ = Poller::create();
|
||||||
for (auto name : service_list) {
|
for (auto name : service_list) {
|
||||||
if (services.count(std::string(name)) == 0) {
|
|
||||||
printf("Unknown service name: %s\n", name);
|
|
||||||
}
|
|
||||||
assert(services.count(std::string(name)) > 0);
|
assert(services.count(std::string(name)) > 0);
|
||||||
|
|
||||||
service serv = services.at(std::string(name));
|
service serv = services.at(std::string(name));
|
||||||
SubSocket *socket = SubSocket::create(message_context.context(), name, address ? address : "127.0.0.1", true);
|
SubSocket *socket = SubSocket::create(message_context.context(), name, address ? address : "127.0.0.1", true, true, serv.queue_size);
|
||||||
assert(socket != 0);
|
assert(socket != 0);
|
||||||
bool is_polled = inList(poll, name) || poll.empty();
|
bool is_polled = inList(poll, name) || poll.empty();
|
||||||
if (is_polled) poller_->registerSocket(socket);
|
if (is_polled) poller_->registerSocket(socket);
|
||||||
@@ -189,11 +186,9 @@ SubMaster::~SubMaster() {
|
|||||||
|
|
||||||
PubMaster::PubMaster(const std::vector<const char *> &service_list) {
|
PubMaster::PubMaster(const std::vector<const char *> &service_list) {
|
||||||
for (auto name : service_list) {
|
for (auto name : service_list) {
|
||||||
if (services.count(name) == 0) {
|
|
||||||
printf("PubMaster Error: unknown service '%s'\n", name);
|
|
||||||
}
|
|
||||||
assert(services.count(name) > 0);
|
assert(services.count(name) > 0);
|
||||||
PubSocket *socket = PubSocket::create(message_context.context(), name);
|
service serv = services.at(std::string(name));
|
||||||
|
PubSocket *socket = PubSocket::create(message_context.context(), name, true, serv.queue_size);
|
||||||
assert(socket);
|
assert(socket);
|
||||||
sockets_[name] = socket;
|
sockets_[name] = socket;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import numbers
|
|||||||
import random
|
import random
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from parameterized import parameterized
|
from openpilot.common.parameterized import parameterized
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from cereal import log, car
|
from cereal import log, car
|
||||||
@@ -30,7 +30,7 @@ def zmq_sleep(t=1):
|
|||||||
|
|
||||||
# TODO: this should take any capnp struct and returrn a msg with random populated data
|
# TODO: this should take any capnp struct and returrn a msg with random populated data
|
||||||
def random_carstate():
|
def random_carstate():
|
||||||
fields = ["vEgo", "aEgo", "gas", "steeringAngleDeg"]
|
fields = ["vEgo", "aEgo", "steeringTorque", "steeringAngleDeg"]
|
||||||
msg = messaging.new_message("carState")
|
msg = messaging.new_message("carState")
|
||||||
cs = msg.carState
|
cs = msg.carState
|
||||||
for f in fields:
|
for f in fields:
|
||||||
@@ -177,8 +177,8 @@ class TestMessaging:
|
|||||||
|
|
||||||
# wait 5 socket timeouts before sending
|
# wait 5 socket timeouts before sending
|
||||||
msg = random_carstate()
|
msg = random_carstate()
|
||||||
delayed_send(sock_timeout*5, pub_sock, msg.to_bytes())
|
|
||||||
start_time = time.monotonic()
|
start_time = time.monotonic()
|
||||||
|
delayed_send(sock_timeout*5, pub_sock, msg.to_bytes())
|
||||||
recvd = messaging.recv_one_retry(sub_sock)
|
recvd = messaging.recv_one_retry(sub_sock)
|
||||||
assert (time.monotonic() - start_time) >= sock_timeout*5
|
assert (time.monotonic() - start_time) >= sock_timeout*5
|
||||||
assert isinstance(recvd, capnp._DynamicStructReader)
|
assert isinstance(recvd, capnp._DynamicStructReader)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import cereal.messaging as messaging
|
|||||||
from cereal.messaging.tests.test_messaging import events, random_sock, random_socks, \
|
from cereal.messaging.tests.test_messaging import events, random_sock, random_socks, \
|
||||||
random_bytes, random_carstate, assert_carstate, \
|
random_bytes, random_carstate, assert_carstate, \
|
||||||
zmq_sleep
|
zmq_sleep
|
||||||
|
from cereal.services import SERVICE_LIST
|
||||||
|
|
||||||
|
|
||||||
class TestSubMaster:
|
class TestSubMaster:
|
||||||
@@ -26,7 +27,9 @@ class TestSubMaster:
|
|||||||
sm = messaging.SubMaster(socks)
|
sm = messaging.SubMaster(socks)
|
||||||
assert sm.frame == -1
|
assert sm.frame == -1
|
||||||
assert not any(sm.updated.values())
|
assert not any(sm.updated.values())
|
||||||
assert not any(sm.alive.values())
|
assert not any(sm.seen.values())
|
||||||
|
on_demand = {s: SERVICE_LIST[s].frequency <= 1e-5 for s in sm.services}
|
||||||
|
assert all(sm.alive[s] == sm.valid[s] == sm.freq_ok[s] == on_demand[s] for s in sm.services)
|
||||||
assert all(t == 0. for t in sm.recv_time.values())
|
assert all(t == 0. for t in sm.recv_time.values())
|
||||||
assert all(f == 0 for f in sm.recv_frame.values())
|
assert all(f == 0 for f in sm.recv_frame.values())
|
||||||
assert all(t == 0 for t in sm.logMonoTime.values())
|
assert all(t == 0 for t in sm.logMonoTime.values())
|
||||||
@@ -83,6 +86,7 @@ class TestSubMaster:
|
|||||||
"cameraOdometry": (20, 10),
|
"cameraOdometry": (20, 10),
|
||||||
"liveCalibration": (4, 4),
|
"liveCalibration": (4, 4),
|
||||||
"carParams": (None, None),
|
"carParams": (None, None),
|
||||||
|
"userBookmark": (None, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
for service, (max_freq, min_freq) in checks.items():
|
for service, (max_freq, min_freq) in checks.items():
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from parameterized import parameterized
|
from openpilot.common.parameterized import parameterized
|
||||||
|
|
||||||
import cereal.services as services
|
import cereal.services as services
|
||||||
from cereal.services import SERVICE_LIST
|
from cereal.services import SERVICE_LIST
|
||||||
|
|||||||
+256
@@ -0,0 +1,256 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Schema-level cereal compat check between sunnypilot and upstream openpilot.
|
||||||
|
|
||||||
|
Rules (per struct matched across sides by typeId):
|
||||||
|
R1 shared ordinal must reference the same type.
|
||||||
|
R2 sunnypilot-only ordinal in a union -> FAIL (unknown discriminant upstream).
|
||||||
|
R3 sunnypilot-only ordinal on a regular field -> OK (additive struct evolution).
|
||||||
|
R4 upstream-only ordinal -> OK.
|
||||||
|
R5 sunnypilot-only struct referenced via an upstream-shared field -> FAIL.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
NO_DISCRIMINANT = 0xFFFF
|
||||||
|
|
||||||
|
|
||||||
|
def hex_id(value: int) -> str:
|
||||||
|
return f"0x{value:016x}"
|
||||||
|
|
||||||
|
|
||||||
|
def encode_type(type_node: Any) -> dict:
|
||||||
|
which = type_node.which()
|
||||||
|
if which == "struct":
|
||||||
|
return {"kind": "struct", "typeId": hex_id(type_node.struct.typeId)}
|
||||||
|
if which == "enum":
|
||||||
|
return {"kind": "enum", "typeId": hex_id(type_node.enum.typeId)}
|
||||||
|
if which == "interface":
|
||||||
|
return {"kind": "interface", "typeId": hex_id(type_node.interface.typeId)}
|
||||||
|
if which == "list":
|
||||||
|
return {"kind": "list", "element": encode_type(type_node.list.elementType)}
|
||||||
|
if which == "anyPointer":
|
||||||
|
return {"kind": "anyPointer"}
|
||||||
|
return {"kind": which}
|
||||||
|
|
||||||
|
|
||||||
|
def encode_field(name: str, field: Any) -> dict:
|
||||||
|
proto = field.proto
|
||||||
|
ordinal = proto.ordinal.explicit if proto.ordinal.which() == "explicit" else None
|
||||||
|
discriminant = proto.discriminantValue if proto.discriminantValue != NO_DISCRIMINANT else None
|
||||||
|
|
||||||
|
if proto.which() == "group":
|
||||||
|
type_desc = {"kind": "group", "typeId": hex_id(proto.group.typeId)}
|
||||||
|
else:
|
||||||
|
type_desc = encode_type(proto.slot.type)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"name": name,
|
||||||
|
"ordinal": ordinal,
|
||||||
|
"discriminant": discriminant,
|
||||||
|
"type": type_desc,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def encode_struct(schema: Any) -> dict:
|
||||||
|
node = schema.node
|
||||||
|
return {
|
||||||
|
"typeId": hex_id(node.id),
|
||||||
|
"displayName": node.displayName,
|
||||||
|
"hasUnion": node.struct.discriminantCount > 0,
|
||||||
|
"fields": [encode_field(name, field) for name, field in schema.fields.items()],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _child_struct_schema(field: Any) -> Any:
|
||||||
|
proto = field.proto
|
||||||
|
if proto.which() == "group":
|
||||||
|
return field.schema
|
||||||
|
type_node = proto.slot.type
|
||||||
|
which = type_node.which()
|
||||||
|
if which == "struct":
|
||||||
|
return field.schema
|
||||||
|
if which == "list":
|
||||||
|
container = field.schema
|
||||||
|
element_type = type_node.list.elementType
|
||||||
|
while element_type.which() == "list":
|
||||||
|
container = container.elementType
|
||||||
|
element_type = element_type.list.elementType
|
||||||
|
if element_type.which() == "struct":
|
||||||
|
return container.elementType
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def collect_schema(root: Any) -> dict[str, dict]:
|
||||||
|
structs: dict[str, dict] = {}
|
||||||
|
stack = [root]
|
||||||
|
while stack:
|
||||||
|
schema = stack.pop()
|
||||||
|
type_id = hex_id(schema.node.id)
|
||||||
|
if type_id in structs:
|
||||||
|
continue
|
||||||
|
structs[type_id] = encode_struct(schema)
|
||||||
|
for _name, field in schema.fields.items():
|
||||||
|
try:
|
||||||
|
child = _child_struct_schema(field)
|
||||||
|
except Exception:
|
||||||
|
child = None
|
||||||
|
if child is not None:
|
||||||
|
stack.append(child)
|
||||||
|
return structs
|
||||||
|
|
||||||
|
|
||||||
|
def load_log(cereal_dir: str) -> Any:
|
||||||
|
import capnp
|
||||||
|
cereal_dir = os.path.abspath(cereal_dir)
|
||||||
|
capnp.remove_import_hook()
|
||||||
|
return capnp.load(os.path.join(cereal_dir, "log.capnp"), imports=[cereal_dir])
|
||||||
|
|
||||||
|
|
||||||
|
def dump_schema(cereal_dir: str, path: str) -> None:
|
||||||
|
log = load_log(cereal_dir)
|
||||||
|
payload = {
|
||||||
|
"root": hex_id(log.Event.schema.node.id),
|
||||||
|
"structs": collect_schema(log.Event.schema),
|
||||||
|
}
|
||||||
|
with open(path, "w", encoding="utf-8") as handle:
|
||||||
|
json.dump(payload, handle, indent=2, sort_keys=True)
|
||||||
|
print(f"wrote schema dump with {len(payload['structs'])} structs to {path}")
|
||||||
|
|
||||||
|
|
||||||
|
def types_equal(a: dict, b: dict) -> bool:
|
||||||
|
if a.get("kind") != b.get("kind"):
|
||||||
|
return False
|
||||||
|
kind = a["kind"]
|
||||||
|
if kind in ("struct", "enum", "interface", "group"):
|
||||||
|
return a.get("typeId") == b.get("typeId")
|
||||||
|
if kind == "list":
|
||||||
|
return types_equal(a["element"], b["element"])
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def type_repr(t: dict) -> str:
|
||||||
|
kind = t.get("kind", "?")
|
||||||
|
if kind in ("struct", "enum", "interface", "group"):
|
||||||
|
return f"{kind}({t.get('typeId')})"
|
||||||
|
if kind == "list":
|
||||||
|
return f"list<{type_repr(t['element'])}>"
|
||||||
|
return kind
|
||||||
|
|
||||||
|
|
||||||
|
def field_is_union_variant(field: dict) -> bool:
|
||||||
|
return field.get("discriminant") is not None
|
||||||
|
|
||||||
|
|
||||||
|
def index_fields_by_ordinal(struct: dict) -> dict[int, dict]:
|
||||||
|
indexed: dict[int, dict] = {}
|
||||||
|
for field in struct["fields"]:
|
||||||
|
ordinal = field.get("ordinal")
|
||||||
|
if ordinal is None:
|
||||||
|
continue
|
||||||
|
indexed[ordinal] = field
|
||||||
|
return indexed
|
||||||
|
|
||||||
|
|
||||||
|
def compare(sunnypilot_dump: dict, upstream_dump: dict) -> list[str]:
|
||||||
|
violations: list[str] = []
|
||||||
|
sunnypilot_structs: dict[str, dict] = sunnypilot_dump["structs"]
|
||||||
|
upstream_structs: dict[str, dict] = upstream_dump["structs"]
|
||||||
|
|
||||||
|
sunnypilot_struct_referenced_from_shared: set[str] = set()
|
||||||
|
|
||||||
|
for type_id, sunnypilot_struct in sunnypilot_structs.items():
|
||||||
|
upstream_struct = upstream_structs.get(type_id)
|
||||||
|
if upstream_struct is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
sunnypilot_fields = index_fields_by_ordinal(sunnypilot_struct)
|
||||||
|
upstream_fields = index_fields_by_ordinal(upstream_struct)
|
||||||
|
display = sunnypilot_struct["displayName"]
|
||||||
|
|
||||||
|
for ordinal, sunnypilot_field in sunnypilot_fields.items():
|
||||||
|
upstream_field = upstream_fields.get(ordinal)
|
||||||
|
if upstream_field is None:
|
||||||
|
if field_is_union_variant(sunnypilot_field):
|
||||||
|
violations.append(
|
||||||
|
f"[R2] {display} @{ordinal} ('{sunnypilot_field['name']}', {type_repr(sunnypilot_field['type'])}): "
|
||||||
|
f"union variant not present upstream. upstream cannot parse this discriminant."
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not types_equal(sunnypilot_field["type"], upstream_field["type"]):
|
||||||
|
violations.append(
|
||||||
|
f"[R1] {display} @{ordinal}: type mismatch. "
|
||||||
|
f"sunnypilot='{sunnypilot_field['name']}' {type_repr(sunnypilot_field['type'])} vs "
|
||||||
|
f"upstream='{upstream_field['name']}' {type_repr(upstream_field['type'])}."
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
cursor = sunnypilot_field["type"]
|
||||||
|
while cursor.get("kind") == "list":
|
||||||
|
cursor = cursor["element"]
|
||||||
|
if cursor.get("kind") in ("struct", "group", "interface") and cursor.get("typeId"):
|
||||||
|
sunnypilot_struct_referenced_from_shared.add(cursor["typeId"])
|
||||||
|
|
||||||
|
for type_id, sunnypilot_struct in sunnypilot_structs.items():
|
||||||
|
if type_id in upstream_structs:
|
||||||
|
continue
|
||||||
|
if type_id in sunnypilot_struct_referenced_from_shared:
|
||||||
|
violations.append(
|
||||||
|
f"[R5] struct {sunnypilot_struct['displayName']} ({type_id}) exists only on sunnypilot "
|
||||||
|
f"but is referenced from an upstream-shared field. upstream cannot resolve this type."
|
||||||
|
)
|
||||||
|
|
||||||
|
return violations
|
||||||
|
|
||||||
|
|
||||||
|
def load_peer(path: str) -> dict:
|
||||||
|
with open(path, "r", encoding="utf-8") as handle:
|
||||||
|
return json.load(handle)
|
||||||
|
|
||||||
|
|
||||||
|
def run_read(cereal_dir: str, peer_path: str) -> int:
|
||||||
|
log = load_log(cereal_dir)
|
||||||
|
peer_dump = load_peer(peer_path)
|
||||||
|
local_dump = {
|
||||||
|
"root": hex_id(log.Event.schema.node.id),
|
||||||
|
"structs": collect_schema(log.Event.schema),
|
||||||
|
}
|
||||||
|
violations = compare(sunnypilot_dump=peer_dump, upstream_dump=local_dump)
|
||||||
|
|
||||||
|
if not violations:
|
||||||
|
print("cereal compat OK: upstream openpilot can parse sunnypilot routes "
|
||||||
|
"(no leaked structs, no ordinal collisions).")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
print(f"cereal compat FAIL: upstream openpilot would misparse sunnypilot routes "
|
||||||
|
f"({len(violations)} violation(s)):")
|
||||||
|
for v in violations:
|
||||||
|
print(f" {v}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="sunnypilot <-> upstream cereal compatibility validator (schema-level)."
|
||||||
|
)
|
||||||
|
mode = parser.add_mutually_exclusive_group(required=True)
|
||||||
|
mode.add_argument("-g", "--generate", action="store_true", help="dump local schema to JSON")
|
||||||
|
mode.add_argument("-r", "--read", action="store_true", help="load peer JSON and diff against local")
|
||||||
|
parser.add_argument("-f", "--file", default="schema.json", help="JSON file path (default: schema.json)")
|
||||||
|
parser.add_argument("--cereal-dir", required=True, help="path to cereal directory containing log.capnp")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.generate:
|
||||||
|
dump_schema(args.cereal_dir, args.file)
|
||||||
|
return 0
|
||||||
|
return run_read(args.cereal_dir, args.file)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
Regular → Executable
+47
-39
@@ -1,39 +1,43 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
from enum import IntEnum
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: this should be automatically determined using the capnp schema
|
||||||
|
class QueueSize(IntEnum):
|
||||||
|
BIG = 10 * 1024 * 1024 # 10MB - video frames, large AI outputs
|
||||||
|
MEDIUM = 2 * 1024 * 1024 # 2MB - high freq (CAN), livestream
|
||||||
|
SMALL = 250 * 1024 # 250KB - most services
|
||||||
|
|
||||||
|
|
||||||
class Service:
|
class Service:
|
||||||
def __init__(self, should_log: bool, frequency: float, decimation: Optional[int] = None):
|
def __init__(self, should_log: bool, frequency: float, decimation: Optional[int] = None,
|
||||||
|
queue_size: QueueSize = QueueSize.SMALL):
|
||||||
self.should_log = should_log
|
self.should_log = should_log
|
||||||
self.frequency = frequency
|
self.frequency = frequency
|
||||||
self.decimation = decimation
|
self.decimation = decimation
|
||||||
|
self.queue_size = queue_size
|
||||||
|
|
||||||
|
|
||||||
_services: dict[str, tuple] = {
|
_services: dict[str, tuple] = {
|
||||||
# service: (should_log, frequency, qlog decimation (optional))
|
# service: (should_log, frequency, qlog decimation (optional))
|
||||||
# note: the "EncodeIdx" packets will still be in the log
|
# note: the "EncodeIdx" packets will still be in the log
|
||||||
"gyroscope": (True, 104., 104),
|
"gyroscope": (True, 104., 104),
|
||||||
"gyroscope2": (True, 100., 100),
|
|
||||||
"accelerometer": (True, 104., 104),
|
"accelerometer": (True, 104., 104),
|
||||||
"accelerometer2": (True, 100., 100),
|
|
||||||
"magnetometer": (True, 25.),
|
|
||||||
"lightSensor": (True, 100., 100),
|
|
||||||
"temperatureSensor": (True, 2., 200),
|
"temperatureSensor": (True, 2., 200),
|
||||||
"temperatureSensor2": (True, 2., 200),
|
|
||||||
"gpsNMEA": (True, 9.),
|
|
||||||
"deviceState": (True, 2., 1),
|
"deviceState": (True, 2., 1),
|
||||||
"touch": (True, 20., 1),
|
"touch": (True, 20., 1),
|
||||||
"can": (True, 100., 2053), # decimation gives ~3 msgs in a full segment
|
"can": (True, 100., 2053, QueueSize.BIG), # decimation gives ~3 msgs in a full segment
|
||||||
"controlsState": (True, 100., 10),
|
"controlsState": (True, 100., 10, QueueSize.MEDIUM),
|
||||||
"selfdriveState": (True, 100., 10),
|
"selfdriveState": (True, 100., 10),
|
||||||
"pandaStates": (True, 10., 1),
|
"pandaStates": (True, 10., 1),
|
||||||
"peripheralState": (True, 2., 1),
|
"peripheralState": (True, 2., 1),
|
||||||
"radarState": (True, 20., 5),
|
"radarState": (True, 20., 5),
|
||||||
"roadEncodeIdx": (False, 20., 1),
|
"roadEncodeIdx": (False, 20., 1),
|
||||||
"liveTracks": (True, 20.),
|
"liveTracks": (True, 20.),
|
||||||
"sendcan": (True, 100., 139),
|
"sendcan": (True, 100., 139, QueueSize.MEDIUM),
|
||||||
"logMessage": (True, 0.),
|
"logMessage": (True, 0., None, QueueSize.BIG),
|
||||||
"errorLogMessage": (True, 0., 1),
|
"errorLogMessage": (True, 0., 1, QueueSize.BIG),
|
||||||
"liveCalibration": (True, 4., 4),
|
"liveCalibration": (True, 4., 4),
|
||||||
"liveTorqueParameters": (True, 4., 1),
|
"liveTorqueParameters": (True, 4., 1),
|
||||||
"liveDelay": (True, 4., 1),
|
"liveDelay": (True, 4., 1),
|
||||||
@@ -42,21 +46,19 @@ _services: dict[str, tuple] = {
|
|||||||
"carControl": (True, 100., 10),
|
"carControl": (True, 100., 10),
|
||||||
"carOutput": (True, 100., 10),
|
"carOutput": (True, 100., 10),
|
||||||
"longitudinalPlan": (True, 20., 10),
|
"longitudinalPlan": (True, 20., 10),
|
||||||
|
"lateralManeuverPlan": (True, 20.),
|
||||||
"driverAssistance": (True, 20., 20),
|
"driverAssistance": (True, 20., 20),
|
||||||
"procLog": (True, 0.5, 15),
|
"procLog": (True, 0.5, 15, QueueSize.BIG),
|
||||||
"gpsLocationExternal": (True, 10., 10),
|
"gpsLocationExternal": (True, 10., 10),
|
||||||
"gpsLocation": (True, 1., 1),
|
"gpsLocation": (True, 1., 1),
|
||||||
"ubloxGnss": (True, 10.),
|
"ubloxGnss": (True, 10.),
|
||||||
"qcomGnss": (True, 2.),
|
"qcomGnss": (True, 2.),
|
||||||
"gnssMeasurements": (True, 10., 10),
|
|
||||||
"clocks": (True, 0.1, 1),
|
"clocks": (True, 0.1, 1),
|
||||||
"ubloxRaw": (True, 20.),
|
"ubloxRaw": (True, 20.),
|
||||||
"livePose": (True, 20., 4),
|
"livePose": (True, 20., 4),
|
||||||
#"liveLocationKalman": (True, 20., 5),
|
|
||||||
"liveParameters": (True, 20., 5),
|
"liveParameters": (True, 20., 5),
|
||||||
"cameraOdometry": (True, 20., 10),
|
"cameraOdometry": (True, 20., 10),
|
||||||
"thumbnail": (True, 1 / 60., 1),
|
"thumbnail": (True, 1 / 60., 1),
|
||||||
"lateralPlan": (True, 20., 5),
|
|
||||||
"onroadEvents": (True, 1., 1),
|
"onroadEvents": (True, 1., 1),
|
||||||
"carParams": (True, 0.02, 1),
|
"carParams": (True, 0.02, 1),
|
||||||
"roadCameraState": (True, 20., 20),
|
"roadCameraState": (True, 20., 20),
|
||||||
@@ -67,40 +69,46 @@ _services: dict[str, tuple] = {
|
|||||||
"wideRoadEncodeIdx": (False, 20., 1),
|
"wideRoadEncodeIdx": (False, 20., 1),
|
||||||
"wideRoadCameraState": (True, 20., 20),
|
"wideRoadCameraState": (True, 20., 20),
|
||||||
"drivingModelData": (True, 20., 10),
|
"drivingModelData": (True, 20., 10),
|
||||||
"modelV2": (True, 20.),
|
"modelV2": (True, 20., None, QueueSize.BIG),
|
||||||
"managerState": (True, 2., 1),
|
"managerState": (True, 2., 1),
|
||||||
"uploaderState": (True, 0., 1),
|
|
||||||
"navInstruction": (True, 1., 10),
|
|
||||||
"navRoute": (True, 0.),
|
|
||||||
"navRouteNavd": (True, 0.),
|
|
||||||
"navThumbnail": (True, 0.),
|
|
||||||
"navModel": (True, 2., 4.),
|
|
||||||
"mapRenderState": (True, 2., 1.),
|
|
||||||
"qRoadEncodeIdx": (False, 20.),
|
"qRoadEncodeIdx": (False, 20.),
|
||||||
"userFlag": (True, 0., 1),
|
"userBookmark": (True, 0., 1),
|
||||||
"soundPressure": (True, 10., 10),
|
"soundPressure": (True, 10., 10),
|
||||||
"rawAudioData": (False, 20.),
|
"rawAudioData": (False, 20.),
|
||||||
|
"bookmarkButton": (True, 0., 1),
|
||||||
|
"audioFeedback": (True, 0., 1),
|
||||||
|
"roadEncodeData": (False, 20., None, QueueSize.BIG),
|
||||||
|
"driverEncodeData": (False, 20., None, QueueSize.BIG),
|
||||||
|
"wideRoadEncodeData": (False, 20., None, QueueSize.BIG),
|
||||||
|
"qRoadEncodeData": (False, 20., None, QueueSize.BIG),
|
||||||
|
|
||||||
"carrotMan": (True, 0.),
|
# sunnypilot
|
||||||
"navInstructionCarrot": (True, 1., 10),
|
"modelManagerSP": (False, 1., 1, QueueSize.BIG),
|
||||||
|
"backupManagerSP": (False, 1., 1, QueueSize.BIG),
|
||||||
|
"selfdriveStateSP": (True, 100., 10),
|
||||||
|
"longitudinalPlanSP": (True, 20., 10),
|
||||||
|
"onroadEventsSP": (True, 1., 1),
|
||||||
|
"carParamsSP": (True, 0.02, 1),
|
||||||
|
"carControlSP": (True, 100., 10),
|
||||||
|
"carStateSP": (True, 100., 10),
|
||||||
|
"liveMapDataSP": (True, 1., 1),
|
||||||
|
"modelDataV2SP": (True, 20., None, QueueSize.BIG),
|
||||||
|
"liveLocationKalman": (True, 20.),
|
||||||
|
|
||||||
|
# infiniteCable
|
||||||
|
"liveCurvatureParameters": (True, 4., 1),
|
||||||
|
|
||||||
# debug
|
# debug
|
||||||
"uiDebug": (True, 0., 1),
|
"uiDebug": (True, 0., 1),
|
||||||
"testJoystick": (True, 0.),
|
"testJoystick": (True, 0.),
|
||||||
"alertDebug": (True, 20., 5),
|
"alertDebug": (True, 20., 5),
|
||||||
"roadEncodeData": (False, 20.),
|
|
||||||
"driverEncodeData": (False, 20.),
|
|
||||||
"wideRoadEncodeData": (False, 20.),
|
|
||||||
"qRoadEncodeData": (False, 20.),
|
|
||||||
"livestreamWideRoadEncodeIdx": (False, 20.),
|
"livestreamWideRoadEncodeIdx": (False, 20.),
|
||||||
"livestreamRoadEncodeIdx": (False, 20.),
|
"livestreamRoadEncodeIdx": (False, 20.),
|
||||||
"livestreamDriverEncodeIdx": (False, 20.),
|
"livestreamDriverEncodeIdx": (False, 20.),
|
||||||
"livestreamWideRoadEncodeData": (False, 20.),
|
"livestreamWideRoadEncodeData": (False, 20., None, QueueSize.MEDIUM),
|
||||||
"livestreamRoadEncodeData": (False, 20.),
|
"livestreamRoadEncodeData": (False, 20., None, QueueSize.MEDIUM),
|
||||||
"livestreamDriverEncodeData": (False, 20.),
|
"livestreamDriverEncodeData": (False, 20., None, QueueSize.MEDIUM),
|
||||||
"customReservedRawData0": (True, 0.),
|
"customReservedRawData0": (True, 0.),
|
||||||
"customReservedRawData1": (True, 0.),
|
|
||||||
"customReservedRawData2": (True, 0.),
|
|
||||||
}
|
}
|
||||||
SERVICE_LIST = {name: Service(*vals) for
|
SERVICE_LIST = {name: Service(*vals) for
|
||||||
idx, (name, vals) in enumerate(_services.items())}
|
idx, (name, vals) in enumerate(_services.items())}
|
||||||
@@ -115,13 +123,13 @@ def build_header():
|
|||||||
h += "#include <map>\n"
|
h += "#include <map>\n"
|
||||||
h += "#include <string>\n"
|
h += "#include <string>\n"
|
||||||
|
|
||||||
h += "struct service { std::string name; bool should_log; int frequency; int decimation; };\n"
|
h += "struct service { std::string name; bool should_log; float frequency; int decimation; size_t queue_size; };\n"
|
||||||
h += "static std::map<std::string, service> services = {\n"
|
h += "static std::map<std::string, service> services = {\n"
|
||||||
for k, v in SERVICE_LIST.items():
|
for k, v in SERVICE_LIST.items():
|
||||||
should_log = "true" if v.should_log else "false"
|
should_log = "true" if v.should_log else "false"
|
||||||
decimation = -1 if v.decimation is None else v.decimation
|
decimation = -1 if v.decimation is None else v.decimation
|
||||||
h += ' { "%s", {"%s", %s, %d, %d}},\n' % \
|
h += ' { "%s", {"%s", %s, %f, %d, %d}},\n' % \
|
||||||
(k, k, should_log, v.frequency, decimation)
|
(k, k, should_log, v.frequency, decimation, v.queue_size)
|
||||||
h += "};\n"
|
h += "};\n"
|
||||||
|
|
||||||
h += "#endif\n"
|
h += "#endif\n"
|
||||||
|
|||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
comment: false
|
|
||||||
coverage:
|
|
||||||
status:
|
|
||||||
project:
|
|
||||||
default:
|
|
||||||
informational: true
|
|
||||||
patch: off
|
|
||||||
|
|
||||||
ignore:
|
|
||||||
- "**/test_*.py"
|
|
||||||
- "selfdrive/test/**"
|
|
||||||
- "system/version.py" # codecov changes depending on if we are in a branch or not
|
|
||||||
- "tools"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
*.cpp
|
|
||||||
+2
-9
@@ -1,12 +1,10 @@
|
|||||||
Import('env', 'envCython', 'arch')
|
Import('env', 'envCython')
|
||||||
|
|
||||||
common_libs = [
|
common_libs = [
|
||||||
'params.cc',
|
'params.cc',
|
||||||
'swaglog.cc',
|
'swaglog.cc',
|
||||||
'util.cc',
|
'util.cc',
|
||||||
'watchdog.cc',
|
|
||||||
'ratekeeper.cc',
|
'ratekeeper.cc',
|
||||||
'clutil.cc',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
_common = env.Library('common', common_libs, LIBS="json11")
|
_common = env.Library('common', common_libs, LIBS="json11")
|
||||||
@@ -20,11 +18,6 @@ if GetOption('extras'):
|
|||||||
# Cython bindings
|
# Cython bindings
|
||||||
params_python = envCython.Program('params_pyx.so', 'params_pyx.pyx', LIBS=envCython['LIBS'] + [_common, 'zmq', 'json11'])
|
params_python = envCython.Program('params_pyx.so', 'params_pyx.pyx', LIBS=envCython['LIBS'] + [_common, 'zmq', 'json11'])
|
||||||
|
|
||||||
SConscript([
|
common_python = [params_python]
|
||||||
'transformations/SConscript',
|
|
||||||
])
|
|
||||||
|
|
||||||
Import('transformations_python')
|
|
||||||
common_python = [params_python, transformations_python]
|
|
||||||
|
|
||||||
Export('common_python')
|
Export('common_python')
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
import jwt
|
|
||||||
import os
|
|
||||||
import requests
|
|
||||||
from datetime import datetime, timedelta, UTC
|
|
||||||
from openpilot.system.hardware.hw import Paths
|
|
||||||
from openpilot.system.version import get_version
|
|
||||||
|
|
||||||
API_HOST = os.getenv('API_HOST', 'https://api.commadotai.com')
|
|
||||||
|
|
||||||
class Api:
|
|
||||||
def __init__(self, dongle_id):
|
|
||||||
self.dongle_id = dongle_id
|
|
||||||
with open(Paths.persist_root()+'/comma/id_rsa') as f:
|
|
||||||
self.private_key = f.read()
|
|
||||||
|
|
||||||
def get(self, *args, **kwargs):
|
|
||||||
return self.request('GET', *args, **kwargs)
|
|
||||||
|
|
||||||
def post(self, *args, **kwargs):
|
|
||||||
return self.request('POST', *args, **kwargs)
|
|
||||||
|
|
||||||
def request(self, method, endpoint, timeout=None, access_token=None, **params):
|
|
||||||
return api_get(endpoint, method=method, timeout=timeout, access_token=access_token, **params)
|
|
||||||
|
|
||||||
def get_token(self, expiry_hours=1):
|
|
||||||
now = datetime.now(UTC).replace(tzinfo=None)
|
|
||||||
payload = {
|
|
||||||
'identity': self.dongle_id,
|
|
||||||
'nbf': now,
|
|
||||||
'iat': now,
|
|
||||||
'exp': now + timedelta(hours=expiry_hours)
|
|
||||||
}
|
|
||||||
token = jwt.encode(payload, self.private_key, algorithm='RS256')
|
|
||||||
if isinstance(token, bytes):
|
|
||||||
token = token.decode('utf8')
|
|
||||||
return token
|
|
||||||
|
|
||||||
|
|
||||||
def api_get(endpoint, method='GET', timeout=None, access_token=None, **params):
|
|
||||||
headers = {}
|
|
||||||
if access_token is not None:
|
|
||||||
headers['Authorization'] = "JWT " + access_token
|
|
||||||
|
|
||||||
headers['User-Agent'] = "openpilot-" + get_version()
|
|
||||||
|
|
||||||
return requests.request(method, API_HOST + "/" + endpoint, timeout=timeout, headers=headers, params=params)
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
from openpilot.common.api.comma_connect import CommaConnectApi
|
||||||
|
|
||||||
|
|
||||||
|
class Api:
|
||||||
|
def __init__(self, dongle_id):
|
||||||
|
self.service = CommaConnectApi(dongle_id)
|
||||||
|
|
||||||
|
def request(self, method, endpoint, **params):
|
||||||
|
return self.service.request(method, endpoint, **params)
|
||||||
|
|
||||||
|
def get(self, *args, **kwargs):
|
||||||
|
return self.service.get(*args, **kwargs)
|
||||||
|
|
||||||
|
def post(self, *args, **kwargs):
|
||||||
|
return self.service.post(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_token(self, payload_extra=None, expiry_hours=1):
|
||||||
|
return self.service.get_token(payload_extra, expiry_hours)
|
||||||
|
|
||||||
|
|
||||||
|
def api_get(endpoint, method='GET', timeout=None, access_token=None, session=None, **params):
|
||||||
|
return CommaConnectApi(None).api_get(endpoint, method, timeout, access_token, session, **params)
|
||||||
|
|
||||||
|
|
||||||
|
def get_key_pair() -> tuple[str, str, str] | tuple[None, None, None]:
|
||||||
|
return CommaConnectApi(None).get_key_pair()
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import jwt
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import unicodedata
|
||||||
|
from datetime import datetime, timedelta, UTC
|
||||||
|
from openpilot.system.hardware.hw import Paths
|
||||||
|
from openpilot.system.version import get_version
|
||||||
|
|
||||||
|
# name: jwt signature algorithm
|
||||||
|
KEYS = {"id_rsa": "RS256",
|
||||||
|
"id_ecdsa": "ES256"}
|
||||||
|
|
||||||
|
|
||||||
|
class BaseApi:
|
||||||
|
def __init__(self, dongle_id, api_host, user_agent="openpilot-"):
|
||||||
|
self.dongle_id = dongle_id
|
||||||
|
self.api_host = api_host
|
||||||
|
self.user_agent = user_agent
|
||||||
|
self.jwt_algorithm, self.private_key, _ = self.get_key_pair()
|
||||||
|
|
||||||
|
def get(self, *args, **kwargs):
|
||||||
|
return self.request('GET', *args, **kwargs)
|
||||||
|
|
||||||
|
def post(self, *args, **kwargs):
|
||||||
|
return self.request('POST', *args, **kwargs)
|
||||||
|
|
||||||
|
def request(self, method, endpoint, timeout=None, access_token=None, **params):
|
||||||
|
return self.api_get(endpoint, method=method, timeout=timeout, access_token=access_token, **params)
|
||||||
|
|
||||||
|
def _get_token(self, payload_extra=None, expiry_hours=1, **extra_payload):
|
||||||
|
now = datetime.now(UTC).replace(tzinfo=None)
|
||||||
|
payload = {
|
||||||
|
'identity': self.dongle_id,
|
||||||
|
'nbf': now,
|
||||||
|
'iat': now,
|
||||||
|
'exp': now + timedelta(hours=expiry_hours),
|
||||||
|
**extra_payload
|
||||||
|
}
|
||||||
|
if payload_extra is not None:
|
||||||
|
payload.update(payload_extra)
|
||||||
|
token = jwt.encode(payload, self.private_key, algorithm=self.jwt_algorithm)
|
||||||
|
if isinstance(token, bytes):
|
||||||
|
token = token.decode('utf8')
|
||||||
|
return token
|
||||||
|
|
||||||
|
def get_token(self, payload_extra=None, expiry_hours=1):
|
||||||
|
return self._get_token(payload_extra, expiry_hours)
|
||||||
|
|
||||||
|
def remove_non_ascii_chars(self, text):
|
||||||
|
normalized_text = unicodedata.normalize('NFD', text)
|
||||||
|
ascii_encoded_text = normalized_text.encode('ascii', 'ignore')
|
||||||
|
return ascii_encoded_text.decode()
|
||||||
|
|
||||||
|
def api_get(self, endpoint, method='GET', timeout=None, access_token=None, session=None, json=None, **params):
|
||||||
|
headers = {}
|
||||||
|
if access_token is not None:
|
||||||
|
headers['Authorization'] = "JWT " + access_token
|
||||||
|
|
||||||
|
version = self.remove_non_ascii_chars(get_version())
|
||||||
|
headers['User-Agent'] = self.user_agent + version
|
||||||
|
|
||||||
|
# TODO: add session to Api
|
||||||
|
req = requests if session is None else session
|
||||||
|
return req.request(method, f"{self.api_host}/{endpoint}", timeout=timeout, headers=headers, json=json, params=params)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_key_pair() -> tuple[str, str, str] | tuple[None, None, None]:
|
||||||
|
for key in KEYS:
|
||||||
|
if os.path.isfile(Paths.persist_root() + f'/comma/{key}') and os.path.isfile(Paths.persist_root() + f'/comma/{key}.pub'):
|
||||||
|
with open(Paths.persist_root() + f'/comma/{key}') as private, open(Paths.persist_root() + f'/comma/{key}.pub') as public:
|
||||||
|
return KEYS[key], private.read(), public.read()
|
||||||
|
return None, None, None
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from openpilot.common.api.base import BaseApi
|
||||||
|
|
||||||
|
API_HOST = os.getenv('API_HOST', 'https://api.commadotai.com')
|
||||||
|
|
||||||
|
|
||||||
|
class CommaConnectApi(BaseApi):
|
||||||
|
def __init__(self, dongle_id):
|
||||||
|
super().__init__(dongle_id, API_HOST)
|
||||||
|
self.user_agent = "openpilot-"
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
#include "common/clutil.h"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "common/util.h"
|
|
||||||
#include "common/swaglog.h"
|
|
||||||
|
|
||||||
namespace { // helper functions
|
|
||||||
|
|
||||||
template <typename Func, typename Id, typename Name>
|
|
||||||
std::string get_info(Func get_info_func, Id id, Name param_name) {
|
|
||||||
size_t size = 0;
|
|
||||||
CL_CHECK(get_info_func(id, param_name, 0, NULL, &size));
|
|
||||||
std::string info(size, '\0');
|
|
||||||
CL_CHECK(get_info_func(id, param_name, size, info.data(), NULL));
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
inline std::string get_platform_info(cl_platform_id id, cl_platform_info name) { return get_info(&clGetPlatformInfo, id, name); }
|
|
||||||
inline std::string get_device_info(cl_device_id id, cl_device_info name) { return get_info(&clGetDeviceInfo, id, name); }
|
|
||||||
|
|
||||||
void cl_print_info(cl_platform_id platform, cl_device_id device) {
|
|
||||||
size_t work_group_size = 0;
|
|
||||||
cl_device_type device_type = 0;
|
|
||||||
clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(work_group_size), &work_group_size, NULL);
|
|
||||||
clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(device_type), &device_type, NULL);
|
|
||||||
const char *type_str = "Other...";
|
|
||||||
switch (device_type) {
|
|
||||||
case CL_DEVICE_TYPE_CPU: type_str ="CL_DEVICE_TYPE_CPU"; break;
|
|
||||||
case CL_DEVICE_TYPE_GPU: type_str = "CL_DEVICE_TYPE_GPU"; break;
|
|
||||||
case CL_DEVICE_TYPE_ACCELERATOR: type_str = "CL_DEVICE_TYPE_ACCELERATOR"; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGD("vendor: %s", get_platform_info(platform, CL_PLATFORM_VENDOR).c_str());
|
|
||||||
LOGD("platform version: %s", get_platform_info(platform, CL_PLATFORM_VERSION).c_str());
|
|
||||||
LOGD("profile: %s", get_platform_info(platform, CL_PLATFORM_PROFILE).c_str());
|
|
||||||
LOGD("extensions: %s", get_platform_info(platform, CL_PLATFORM_EXTENSIONS).c_str());
|
|
||||||
LOGD("name: %s", get_device_info(device, CL_DEVICE_NAME).c_str());
|
|
||||||
LOGD("device version: %s", get_device_info(device, CL_DEVICE_VERSION).c_str());
|
|
||||||
LOGD("max work group size: %zu", work_group_size);
|
|
||||||
LOGD("type = %d, %s", (int)device_type, type_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cl_print_build_errors(cl_program program, cl_device_id device) {
|
|
||||||
cl_build_status status;
|
|
||||||
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_STATUS, sizeof(status), &status, NULL);
|
|
||||||
size_t log_size;
|
|
||||||
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size);
|
|
||||||
std::string log(log_size, '\0');
|
|
||||||
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, log_size, &log[0], NULL);
|
|
||||||
|
|
||||||
LOGE("build failed; status=%d, log: %s", status, log.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
cl_device_id cl_get_device_id(cl_device_type device_type) {
|
|
||||||
cl_uint num_platforms = 0;
|
|
||||||
CL_CHECK(clGetPlatformIDs(0, NULL, &num_platforms));
|
|
||||||
std::unique_ptr<cl_platform_id[]> platform_ids = std::make_unique<cl_platform_id[]>(num_platforms);
|
|
||||||
CL_CHECK(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL));
|
|
||||||
|
|
||||||
for (size_t i = 0; i < num_platforms; ++i) {
|
|
||||||
LOGD("platform[%zu] CL_PLATFORM_NAME: %s", i, get_platform_info(platform_ids[i], CL_PLATFORM_NAME).c_str());
|
|
||||||
|
|
||||||
// Get first device
|
|
||||||
if (cl_device_id device_id = NULL; clGetDeviceIDs(platform_ids[i], device_type, 1, &device_id, NULL) == 0 && device_id) {
|
|
||||||
cl_print_info(platform_ids[i], device_id);
|
|
||||||
return device_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOGE("No valid openCL platform found");
|
|
||||||
assert(0);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
cl_context cl_create_context(cl_device_id device_id) {
|
|
||||||
return CL_CHECK_ERR(clCreateContext(NULL, 1, &device_id, NULL, NULL, &err));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cl_release_context(cl_context context) {
|
|
||||||
clReleaseContext(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
cl_program cl_program_from_file(cl_context ctx, cl_device_id device_id, const char* path, const char* args) {
|
|
||||||
return cl_program_from_source(ctx, device_id, util::read_file(path), args);
|
|
||||||
}
|
|
||||||
|
|
||||||
cl_program cl_program_from_source(cl_context ctx, cl_device_id device_id, const std::string& src, const char* args) {
|
|
||||||
const char *csrc = src.c_str();
|
|
||||||
cl_program prg = CL_CHECK_ERR(clCreateProgramWithSource(ctx, 1, &csrc, NULL, &err));
|
|
||||||
if (int err = clBuildProgram(prg, 1, &device_id, args, NULL, NULL); err != 0) {
|
|
||||||
cl_print_build_errors(prg, device_id);
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
return prg;
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include <OpenCL/cl.h>
|
|
||||||
#else
|
|
||||||
#include <CL/cl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#define CL_CHECK(_expr) \
|
|
||||||
do { \
|
|
||||||
assert(CL_SUCCESS == (_expr)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define CL_CHECK_ERR(_expr) \
|
|
||||||
({ \
|
|
||||||
cl_int err = CL_INVALID_VALUE; \
|
|
||||||
__typeof__(_expr) _ret = _expr; \
|
|
||||||
assert(_ret&& err == CL_SUCCESS); \
|
|
||||||
_ret; \
|
|
||||||
})
|
|
||||||
|
|
||||||
cl_device_id cl_get_device_id(cl_device_type device_type);
|
|
||||||
cl_context cl_create_context(cl_device_id device_id);
|
|
||||||
void cl_release_context(cl_context context);
|
|
||||||
cl_program cl_program_from_source(cl_context ctx, cl_device_id device_id, const std::string& src, const char* args = nullptr);
|
|
||||||
cl_program cl_program_from_file(cl_context ctx, cl_device_id device_id, const char* path, const char* args);
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import numpy as np
|
|
||||||
|
|
||||||
class Conversions:
|
|
||||||
# Speed
|
|
||||||
MPH_TO_KPH = 1.609344
|
|
||||||
KPH_TO_MPH = 1. / MPH_TO_KPH
|
|
||||||
MS_TO_KPH = 3.6
|
|
||||||
KPH_TO_MS = 1. / MS_TO_KPH
|
|
||||||
MS_TO_MPH = MS_TO_KPH * KPH_TO_MPH
|
|
||||||
MPH_TO_MS = MPH_TO_KPH * KPH_TO_MS
|
|
||||||
MS_TO_KNOTS = 1.9438
|
|
||||||
KNOTS_TO_MS = 1. / MS_TO_KNOTS
|
|
||||||
|
|
||||||
# Angle
|
|
||||||
DEG_TO_RAD = np.pi / 180.
|
|
||||||
RAD_TO_DEG = 1. / DEG_TO_RAD
|
|
||||||
|
|
||||||
# Mass
|
|
||||||
LB_TO_KG = 0.453592
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# remove all keys that end in DEPRECATED
|
|
||||||
def strip_deprecated_keys(d):
|
|
||||||
for k in list(d.keys()):
|
|
||||||
if isinstance(k, str):
|
|
||||||
if k.endswith('DEPRECATED'):
|
|
||||||
d.pop(k)
|
|
||||||
elif isinstance(d[k], dict):
|
|
||||||
strip_deprecated_keys(d[k])
|
|
||||||
return d
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import platform
|
|
||||||
|
|
||||||
|
|
||||||
def suffix():
|
|
||||||
if platform.system() == "Darwin":
|
|
||||||
return ".dylib"
|
|
||||||
else:
|
|
||||||
return ".so"
|
|
||||||
Executable
+55
@@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import sys
|
||||||
|
import math
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
CHUNK_SIZE = 45 * 1024 * 1024 # 45MB, under GitHub's 50MB limit
|
||||||
|
|
||||||
|
def get_chunk_name(name, idx, num_chunks):
|
||||||
|
return f"{name}.chunk{idx+1:02d}of{num_chunks:02d}"
|
||||||
|
|
||||||
|
def get_manifest_path(name):
|
||||||
|
return f"{name}.chunkmanifest"
|
||||||
|
|
||||||
|
def _chunk_paths(path, num_chunks):
|
||||||
|
return [get_manifest_path(path)] + [get_chunk_name(path, i, num_chunks) for i in range(num_chunks)]
|
||||||
|
|
||||||
|
def get_chunk_targets(path, file_size):
|
||||||
|
num_chunks = math.ceil(file_size / CHUNK_SIZE)
|
||||||
|
return _chunk_paths(path, num_chunks)
|
||||||
|
|
||||||
|
def chunk_file(path, targets):
|
||||||
|
manifest_path, *chunk_paths = targets
|
||||||
|
with open(path, 'rb') as f:
|
||||||
|
data = f.read()
|
||||||
|
actual_num_chunks = max(1, math.ceil(len(data) / CHUNK_SIZE))
|
||||||
|
assert len(chunk_paths) >= actual_num_chunks, f"Allowed {len(chunk_paths)} chunks but needs at least {actual_num_chunks}, for path {path}"
|
||||||
|
for i, chunk_path in enumerate(chunk_paths):
|
||||||
|
with open(chunk_path, 'wb') as f:
|
||||||
|
f.write(data[i * CHUNK_SIZE:(i + 1) * CHUNK_SIZE])
|
||||||
|
Path(manifest_path).write_text(str(len(chunk_paths)))
|
||||||
|
os.remove(path)
|
||||||
|
|
||||||
|
def get_existing_chunks(path):
|
||||||
|
if os.path.isfile(path):
|
||||||
|
return [path]
|
||||||
|
if os.path.isfile(manifest := get_manifest_path(path)):
|
||||||
|
num_chunks = int(Path(manifest).read_text().strip())
|
||||||
|
return _chunk_paths(path, num_chunks)
|
||||||
|
raise FileNotFoundError(path)
|
||||||
|
|
||||||
|
def read_file_chunked(path):
|
||||||
|
manifest_path = get_manifest_path(path)
|
||||||
|
if os.path.isfile(manifest_path):
|
||||||
|
num_chunks = int(Path(manifest_path).read_text().strip())
|
||||||
|
return b''.join(Path(get_chunk_name(path, i, num_chunks)).read_bytes() for i in range(num_chunks))
|
||||||
|
if os.path.isfile(path):
|
||||||
|
return Path(path).read_bytes()
|
||||||
|
raise FileNotFoundError(path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
path = sys.argv[1]
|
||||||
|
chunk_paths = get_chunk_targets(path, os.path.getsize(path))
|
||||||
|
chunk_file(path, chunk_paths)
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
import io
|
|
||||||
import os
|
|
||||||
import tempfile
|
|
||||||
import contextlib
|
|
||||||
import zstandard as zstd
|
|
||||||
|
|
||||||
LOG_COMPRESSION_LEVEL = 10 # little benefit up to level 15. level ~17 is a small step change
|
|
||||||
|
|
||||||
|
|
||||||
class CallbackReader:
|
|
||||||
"""Wraps a file, but overrides the read method to also
|
|
||||||
call a callback function with the number of bytes read so far."""
|
|
||||||
def __init__(self, f, callback, *args):
|
|
||||||
self.f = f
|
|
||||||
self.callback = callback
|
|
||||||
self.cb_args = args
|
|
||||||
self.total_read = 0
|
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
|
||||||
return getattr(self.f, attr)
|
|
||||||
|
|
||||||
def read(self, *args, **kwargs):
|
|
||||||
chunk = self.f.read(*args, **kwargs)
|
|
||||||
self.total_read += len(chunk)
|
|
||||||
self.callback(*self.cb_args, self.total_read)
|
|
||||||
return chunk
|
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: str = None, newline: str = None,
|
|
||||||
overwrite: bool = False):
|
|
||||||
"""Write to a file atomically using a temporary file in the same directory as the destination file."""
|
|
||||||
dir_name = os.path.dirname(path)
|
|
||||||
|
|
||||||
if not overwrite and os.path.exists(path):
|
|
||||||
raise FileExistsError(f"File '{path}' already exists. To overwrite it, set 'overwrite' to True.")
|
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(mode=mode, buffering=buffering, encoding=encoding, newline=newline, dir=dir_name, delete=False) as tmp_file:
|
|
||||||
yield tmp_file
|
|
||||||
tmp_file_name = tmp_file.name
|
|
||||||
os.replace(tmp_file_name, path)
|
|
||||||
|
|
||||||
|
|
||||||
def get_upload_stream(filepath: str, should_compress: bool) -> tuple[io.BufferedIOBase, int]:
|
|
||||||
if not should_compress:
|
|
||||||
file_size = os.path.getsize(filepath)
|
|
||||||
file_stream = open(filepath, "rb")
|
|
||||||
return file_stream, file_size
|
|
||||||
|
|
||||||
# Compress the file on the fly
|
|
||||||
compressed_stream = io.BytesIO()
|
|
||||||
compressor = zstd.ZstdCompressor(level=LOG_COMPRESSION_LEVEL)
|
|
||||||
|
|
||||||
with open(filepath, "rb") as f:
|
|
||||||
compressor.copy_stream(f, compressed_stream)
|
|
||||||
compressed_size = compressed_stream.tell()
|
|
||||||
compressed_stream.seek(0)
|
|
||||||
return compressed_stream, compressed_size
|
|
||||||
+1
-36
@@ -1,8 +1,4 @@
|
|||||||
import numpy as np
|
|
||||||
from collections import deque
|
|
||||||
|
|
||||||
class FirstOrderFilter:
|
class FirstOrderFilter:
|
||||||
# first order filter
|
|
||||||
def __init__(self, x0, rc, dt, initialized=True):
|
def __init__(self, x0, rc, dt, initialized=True):
|
||||||
self.x = x0
|
self.x = x0
|
||||||
self.dt = dt
|
self.dt = dt
|
||||||
@@ -32,38 +28,7 @@ class BounceFilter(FirstOrderFilter):
|
|||||||
scale = self.dt / (1.0 / 60.0) # tuned at 60 fps
|
scale = self.dt / (1.0 / 60.0) # tuned at 60 fps
|
||||||
self.velocity.x += (x - self.x) * self.bounce * scale * self.dt
|
self.velocity.x += (x - self.x) * self.bounce * scale * self.dt
|
||||||
self.velocity.update(0.0)
|
self.velocity.update(0.0)
|
||||||
if abs(self.velocity.x) < 1e-5:
|
if abs(self.velocity.x) < 1e-3:
|
||||||
self.velocity.x = 0.0
|
self.velocity.x = 0.0
|
||||||
self.x += self.velocity.x
|
self.x += self.velocity.x
|
||||||
return self.x
|
return self.x
|
||||||
|
|
||||||
class MyMovingAverage:
|
|
||||||
def __init__(self, window_size, value=None):
|
|
||||||
self.window_size = window_size
|
|
||||||
if (value is not None):
|
|
||||||
self.values = deque([value] * window_size, maxlen=window_size)
|
|
||||||
self.sum = value * window_size
|
|
||||||
self.result = value
|
|
||||||
else:
|
|
||||||
self.values = deque(maxlen=window_size)
|
|
||||||
self.sum = 0
|
|
||||||
self.result = 0
|
|
||||||
|
|
||||||
def set(self, value):
|
|
||||||
self.values.clear()
|
|
||||||
self.values.append(value)
|
|
||||||
self.sum = value
|
|
||||||
self.result = value
|
|
||||||
return value
|
|
||||||
|
|
||||||
def set_all(self, value):
|
|
||||||
self.values = deque([value] * self.window_size, maxlen=self.window_size)
|
|
||||||
self.sum = value * self.window_size
|
|
||||||
self.result = value
|
|
||||||
return value
|
|
||||||
|
|
||||||
def process(self, value, median=False):
|
|
||||||
self.values.append(value)
|
|
||||||
self.sum = sum(self.values)
|
|
||||||
self.result = float(np.median(self.values)) if median else float(self.sum) / len(self.values)
|
|
||||||
return self.result
|
|
||||||
|
|||||||
+7
-7
@@ -1,30 +1,30 @@
|
|||||||
from functools import cache
|
from functools import cache
|
||||||
import subprocess
|
import subprocess
|
||||||
from openpilot.common.run import run_cmd, run_cmd_default
|
from openpilot.common.utils import run_cmd, run_cmd_default
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_commit(cwd: str = None, branch: str = "HEAD") -> str:
|
def get_commit(cwd: str | None = None, branch: str = "HEAD") -> str:
|
||||||
return run_cmd_default(["git", "rev-parse", branch], cwd=cwd)
|
return run_cmd_default(["git", "rev-parse", branch], cwd=cwd)
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_commit_date(cwd: str = None, commit: str = "HEAD") -> str:
|
def get_commit_date(cwd: str | None = None, commit: str = "HEAD") -> str:
|
||||||
return run_cmd_default(["git", "show", "--no-patch", "--format='%ct %ci'", commit], cwd=cwd)
|
return run_cmd_default(["git", "show", "--no-patch", "--format='%ct %ci'", commit], cwd=cwd)
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_short_branch(cwd: str = None) -> str:
|
def get_short_branch(cwd: str | None = None) -> str:
|
||||||
return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=cwd)
|
return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=cwd)
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_branch(cwd: str = None) -> str:
|
def get_branch(cwd: str | None = None) -> str:
|
||||||
return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], cwd=cwd)
|
return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], cwd=cwd)
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_origin(cwd: str = None) -> str:
|
def get_origin(cwd: str | None = None) -> str:
|
||||||
try:
|
try:
|
||||||
local_branch = run_cmd(["git", "name-rev", "--name-only", "HEAD"], cwd=cwd)
|
local_branch = run_cmd(["git", "name-rev", "--name-only", "HEAD"], cwd=cwd)
|
||||||
tracking_remote = run_cmd(["git", "config", "branch." + local_branch + ".remote"], cwd=cwd)
|
tracking_remote = run_cmd(["git", "config", "branch." + local_branch + ".remote"], cwd=cwd)
|
||||||
@@ -34,7 +34,7 @@ def get_origin(cwd: str = None) -> str:
|
|||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_normalized_origin(cwd: str = None) -> str:
|
def get_normalized_origin(cwd: str | None = None) -> str:
|
||||||
return get_origin(cwd) \
|
return get_origin(cwd) \
|
||||||
.replace("git@", "", 1) \
|
.replace("git@", "", 1) \
|
||||||
.replace(".git", "", 1) \
|
.replace(".git", "", 1) \
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import os
|
||||||
|
import fcntl
|
||||||
|
import ctypes
|
||||||
|
|
||||||
|
# I2C constants from /usr/include/linux/i2c-dev.h
|
||||||
|
I2C_SLAVE = 0x0703
|
||||||
|
I2C_SLAVE_FORCE = 0x0706
|
||||||
|
I2C_SMBUS = 0x0720
|
||||||
|
|
||||||
|
# SMBus transfer types
|
||||||
|
I2C_SMBUS_READ = 1
|
||||||
|
I2C_SMBUS_WRITE = 0
|
||||||
|
I2C_SMBUS_BYTE_DATA = 2
|
||||||
|
I2C_SMBUS_I2C_BLOCK_DATA = 8
|
||||||
|
|
||||||
|
I2C_SMBUS_BLOCK_MAX = 32
|
||||||
|
|
||||||
|
|
||||||
|
class _I2cSmbusData(ctypes.Union):
|
||||||
|
_fields_ = [
|
||||||
|
("byte", ctypes.c_uint8),
|
||||||
|
("word", ctypes.c_uint16),
|
||||||
|
("block", ctypes.c_uint8 * (I2C_SMBUS_BLOCK_MAX + 2)),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class _I2cSmbusIoctlData(ctypes.Structure):
|
||||||
|
_fields_ = [
|
||||||
|
("read_write", ctypes.c_uint8),
|
||||||
|
("command", ctypes.c_uint8),
|
||||||
|
("size", ctypes.c_uint32),
|
||||||
|
("data", ctypes.POINTER(_I2cSmbusData)),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class SMBus:
|
||||||
|
def __init__(self, bus: int):
|
||||||
|
self._fd = os.open(f'/dev/i2c-{bus}', os.O_RDWR)
|
||||||
|
|
||||||
|
def __enter__(self) -> 'SMBus':
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, *args) -> None:
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def close(self) -> None:
|
||||||
|
if hasattr(self, '_fd') and self._fd >= 0:
|
||||||
|
os.close(self._fd)
|
||||||
|
self._fd = -1
|
||||||
|
|
||||||
|
def _set_address(self, addr: int, force: bool = False) -> None:
|
||||||
|
ioctl_arg = I2C_SLAVE_FORCE if force else I2C_SLAVE
|
||||||
|
fcntl.ioctl(self._fd, ioctl_arg, addr)
|
||||||
|
|
||||||
|
def _smbus_access(self, read_write: int, command: int, size: int, data: _I2cSmbusData) -> None:
|
||||||
|
ioctl_data = _I2cSmbusIoctlData(read_write, command, size, ctypes.pointer(data))
|
||||||
|
fcntl.ioctl(self._fd, I2C_SMBUS, ioctl_data)
|
||||||
|
|
||||||
|
def read_byte_data(self, addr: int, register: int, force: bool = False) -> int:
|
||||||
|
self._set_address(addr, force)
|
||||||
|
data = _I2cSmbusData()
|
||||||
|
self._smbus_access(I2C_SMBUS_READ, register, I2C_SMBUS_BYTE_DATA, data)
|
||||||
|
return int(data.byte)
|
||||||
|
|
||||||
|
def write_byte_data(self, addr: int, register: int, value: int, force: bool = False) -> None:
|
||||||
|
self._set_address(addr, force)
|
||||||
|
data = _I2cSmbusData()
|
||||||
|
data.byte = value & 0xFF
|
||||||
|
self._smbus_access(I2C_SMBUS_WRITE, register, I2C_SMBUS_BYTE_DATA, data)
|
||||||
|
|
||||||
|
def read_i2c_block_data(self, addr: int, register: int, length: int, force: bool = False) -> list[int]:
|
||||||
|
self._set_address(addr, force)
|
||||||
|
if not (0 <= length <= I2C_SMBUS_BLOCK_MAX):
|
||||||
|
raise ValueError(f"length must be 0..{I2C_SMBUS_BLOCK_MAX}")
|
||||||
|
|
||||||
|
data = _I2cSmbusData()
|
||||||
|
data.block[0] = length
|
||||||
|
self._smbus_access(I2C_SMBUS_READ, register, I2C_SMBUS_I2C_BLOCK_DATA, data)
|
||||||
|
read_len = int(data.block[0]) or length
|
||||||
|
read_len = min(read_len, length)
|
||||||
|
return [int(b) for b in data.block[1 : read_len + 1]]
|
||||||
@@ -199,7 +199,6 @@ class SwagLogger(logging.Logger):
|
|||||||
co = f.f_code
|
co = f.f_code
|
||||||
filename = os.path.normcase(co.co_filename)
|
filename = os.path.normcase(co.co_filename)
|
||||||
|
|
||||||
# TODO: is this pylint exception correct?
|
|
||||||
if filename == _srcfile:
|
if filename == _srcfile:
|
||||||
f = f.f_back
|
f = f.f_back
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
typedef struct vec3 {
|
|
||||||
float v[3];
|
|
||||||
} vec3;
|
|
||||||
|
|
||||||
typedef struct vec4 {
|
|
||||||
float v[4];
|
|
||||||
} vec4;
|
|
||||||
|
|
||||||
typedef struct mat3 {
|
|
||||||
float v[3*3];
|
|
||||||
} mat3;
|
|
||||||
|
|
||||||
typedef struct mat4 {
|
|
||||||
float v[4*4];
|
|
||||||
} mat4;
|
|
||||||
|
|
||||||
static inline mat3 matmul3(const mat3 &a, const mat3 &b) {
|
|
||||||
mat3 ret = {{0.0}};
|
|
||||||
for (int r=0; r<3; r++) {
|
|
||||||
for (int c=0; c<3; c++) {
|
|
||||||
float v = 0.0;
|
|
||||||
for (int k=0; k<3; k++) {
|
|
||||||
v += a.v[r*3+k] * b.v[k*3+c];
|
|
||||||
}
|
|
||||||
ret.v[r*3+c] = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline vec3 matvecmul3(const mat3 &a, const vec3 &b) {
|
|
||||||
vec3 ret = {{0.0}};
|
|
||||||
for (int r=0; r<3; r++) {
|
|
||||||
for (int c=0; c<3; c++) {
|
|
||||||
ret.v[r] += a.v[r*3+c] * b.v[c];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline mat4 matmul(const mat4 &a, const mat4 &b) {
|
|
||||||
mat4 ret = {{0.0}};
|
|
||||||
for (int r=0; r<4; r++) {
|
|
||||||
for (int c=0; c<4; c++) {
|
|
||||||
float v = 0.0;
|
|
||||||
for (int k=0; k<4; k++) {
|
|
||||||
v += a.v[r*4+k] * b.v[k*4+c];
|
|
||||||
}
|
|
||||||
ret.v[r*4+c] = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline vec4 matvecmul(const mat4 &a, const vec4 &b) {
|
|
||||||
vec4 ret = {{0.0}};
|
|
||||||
for (int r=0; r<4; r++) {
|
|
||||||
for (int c=0; c<4; c++) {
|
|
||||||
ret.v[r] += a.v[r*4+c] * b.v[c];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// scales the input and output space of a transformation matrix
|
|
||||||
// that assumes pixel-center origin.
|
|
||||||
static inline mat3 transform_scale_buffer(const mat3 &in, float s) {
|
|
||||||
// in_pt = ( transform(out_pt/s + 0.5) - 0.5) * s
|
|
||||||
|
|
||||||
mat3 transform_out = {{
|
|
||||||
1.0f/s, 0.0f, 0.5f,
|
|
||||||
0.0f, 1.0f/s, 0.5f,
|
|
||||||
0.0f, 0.0f, 1.0f,
|
|
||||||
}};
|
|
||||||
|
|
||||||
mat3 transform_in = {{
|
|
||||||
s, 0.0f, -0.5f*s,
|
|
||||||
0.0f, s, -0.5f*s,
|
|
||||||
0.0f, 0.0f, 1.0f,
|
|
||||||
}};
|
|
||||||
|
|
||||||
return matmul3(transform_in, matmul3(in, transform_out));
|
|
||||||
}
|
|
||||||
@@ -8,13 +8,12 @@ import functools
|
|||||||
import threading
|
import threading
|
||||||
from cereal.messaging import PubMaster
|
from cereal.messaging import PubMaster
|
||||||
from cereal.services import SERVICE_LIST
|
from cereal.services import SERVICE_LIST
|
||||||
from openpilot.common.mock.generators import generate_livePose, generate_liveLocationKalman
|
from openpilot.common.mock.generators import generate_livePose
|
||||||
from openpilot.common.realtime import Ratekeeper
|
from openpilot.common.realtime import Ratekeeper
|
||||||
|
|
||||||
|
|
||||||
MOCK_GENERATOR = {
|
MOCK_GENERATOR = {
|
||||||
"livePose": generate_livePose,
|
"livePose": generate_livePose
|
||||||
"liveLocationKalman": generate_liveLocationKalman
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,6 @@
|
|||||||
from cereal import messaging
|
from cereal import messaging
|
||||||
|
|
||||||
|
|
||||||
LOCATION1 = (32.7174, -117.16277)
|
|
||||||
LOCATION2 = (32.7558, -117.2037)
|
|
||||||
|
|
||||||
LLK_DECIMATION = 10
|
|
||||||
RENDER_FRAMES = 15
|
|
||||||
DEFAULT_ITERATIONS = RENDER_FRAMES * LLK_DECIMATION
|
|
||||||
|
|
||||||
|
|
||||||
def generate_liveLocationKalman(location=LOCATION1):
|
|
||||||
msg = messaging.new_message('liveLocationKalman')
|
|
||||||
msg.liveLocationKalman.positionGeodetic = {'value': [*location, 0], 'std': [0., 0., 0.], 'valid': True}
|
|
||||||
msg.liveLocationKalman.positionECEF = {'value': [0., 0., 0.], 'std': [0., 0., 0.], 'valid': True}
|
|
||||||
msg.liveLocationKalman.calibratedOrientationNED = {'value': [0., 0., 0.], 'std': [0., 0., 0.], 'valid': True}
|
|
||||||
msg.liveLocationKalman.velocityCalibrated = {'value': [0., 0., 0.], 'std': [0., 0., 0.], 'valid': True}
|
|
||||||
msg.liveLocationKalman.status = 'valid'
|
|
||||||
msg.liveLocationKalman.gpsOK = True
|
|
||||||
return msg
|
|
||||||
|
|
||||||
|
|
||||||
def generate_livePose():
|
def generate_livePose():
|
||||||
msg = messaging.new_message('livePose')
|
msg = messaging.new_message('livePose')
|
||||||
meas = {'x': 0.0, 'y': 0.0, 'z': 0.0, 'xStd': 0.0, 'yStd': 0.0, 'zStd': 0.0, 'valid': True}
|
meas = {'x': 0.0, 'y': 0.0, 'z': 0.0, 'xStd': 0.0, 'yStd': 0.0, 'zStd': 0.0, 'valid': True}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import pytest
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
|
||||||
|
def _to_safe_name(s):
|
||||||
|
return re.sub(r"[^a-zA-Z0-9_]+", "_", str(s)).strip("_")
|
||||||
|
|
||||||
|
|
||||||
|
class parameterized:
|
||||||
|
@staticmethod
|
||||||
|
def expand(cases):
|
||||||
|
cases = list(cases)
|
||||||
|
|
||||||
|
if not cases:
|
||||||
|
return lambda func: pytest.mark.skip("no parameterized cases")(func)
|
||||||
|
|
||||||
|
def decorator(func):
|
||||||
|
params = [p for p in inspect.signature(func).parameters if p != 'self']
|
||||||
|
normalized = [c if isinstance(c, tuple) else (c,) for c in cases]
|
||||||
|
# Infer arg count from first case so extra params (e.g. from @given) are left untouched
|
||||||
|
expand_params = params[: len(normalized[0])]
|
||||||
|
if len(expand_params) == 1:
|
||||||
|
return pytest.mark.parametrize(expand_params[0], [c[0] for c in normalized])(func)
|
||||||
|
return pytest.mark.parametrize(', '.join(expand_params), normalized)(func)
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def parameterized_class(attrs, input_list=None):
|
||||||
|
if isinstance(attrs, list) and (not attrs or isinstance(attrs[0], dict)):
|
||||||
|
params_list = attrs
|
||||||
|
else:
|
||||||
|
assert input_list is not None
|
||||||
|
attr_names = (attrs,) if isinstance(attrs, str) else tuple(attrs)
|
||||||
|
params_list = [dict(zip(attr_names, v if isinstance(v, (tuple, list)) else (v,), strict=False)) for v in input_list]
|
||||||
|
|
||||||
|
def decorator(cls):
|
||||||
|
globs = sys._getframe(1).f_globals
|
||||||
|
for i, params in enumerate(params_list):
|
||||||
|
# append sanitized string param values so pytest -k can filter by them
|
||||||
|
suffix = "_".join(filter(None, (_to_safe_name(v) for v in params.values() if isinstance(v, str))))
|
||||||
|
name = f"{cls.__name__}_{i}" + (f"_{suffix}" if suffix else "")
|
||||||
|
new_cls = type(name, (cls,), dict(params))
|
||||||
|
new_cls.__module__ = cls.__module__
|
||||||
|
new_cls.__test__ = True # override inherited False so pytest collects this subclass
|
||||||
|
globs[name] = new_cls
|
||||||
|
# Don't collect the un-parametrised base, but return it so outer decorators
|
||||||
|
# (e.g. @pytest.mark.skip) land on it and propagate to subclasses via MRO.
|
||||||
|
cls.__test__ = False
|
||||||
|
return cls
|
||||||
|
|
||||||
|
return decorator
|
||||||
+4
-2
@@ -103,10 +103,12 @@ Params::~Params() {
|
|||||||
assert(queue.empty());
|
assert(queue.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Params::allKeys() const {
|
std::vector<std::string> Params::allKeys(ParamKeyFlag flag) const {
|
||||||
std::vector<std::string> ret;
|
std::vector<std::string> ret;
|
||||||
for (auto &p : keys) {
|
for (auto &p : keys) {
|
||||||
ret.push_back(p.first);
|
if (flag == ALL || (p.second.flags & flag)) {
|
||||||
|
ret.push_back(p.first);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-23
@@ -18,6 +18,7 @@ enum ParamKeyFlag {
|
|||||||
DONT_LOG = 0x20,
|
DONT_LOG = 0x20,
|
||||||
DEVELOPMENT_ONLY = 0x40,
|
DEVELOPMENT_ONLY = 0x40,
|
||||||
CLEAR_ON_IGNITION_ON = 0x80,
|
CLEAR_ON_IGNITION_ON = 0x80,
|
||||||
|
BACKUP = 0x100,
|
||||||
ALL = 0xFFFFFFFF
|
ALL = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ public:
|
|||||||
Params(const Params&) = delete;
|
Params(const Params&) = delete;
|
||||||
Params& operator=(const Params&) = delete;
|
Params& operator=(const Params&) = delete;
|
||||||
|
|
||||||
std::vector<std::string> allKeys() const;
|
std::vector<std::string> allKeys(ParamKeyFlag flag = ALL) const;
|
||||||
bool checkKey(const std::string &key);
|
bool checkKey(const std::string &key);
|
||||||
ParamKeyFlag getKeyFlag(const std::string &key);
|
ParamKeyFlag getKeyFlag(const std::string &key);
|
||||||
ParamKeyType getKeyType(const std::string &key);
|
ParamKeyType getKeyType(const std::string &key);
|
||||||
@@ -63,14 +64,6 @@ public:
|
|||||||
inline bool getBool(const std::string &key, bool block = false) {
|
inline bool getBool(const std::string &key, bool block = false) {
|
||||||
return get(key, block) == "1";
|
return get(key, block) == "1";
|
||||||
}
|
}
|
||||||
inline int getInt(const std::string &key, bool block = false) {
|
|
||||||
std::string value = get(key, block);
|
|
||||||
return value.empty() ? 0 : std::stoi(value);
|
|
||||||
}
|
|
||||||
inline float getFloat(const std::string &key, bool block = false) {
|
|
||||||
std::string value = get(key, block);
|
|
||||||
return value.empty() ? 0.0 : std::stof(value);
|
|
||||||
}
|
|
||||||
std::map<std::string, std::string> readAll();
|
std::map<std::string, std::string> readAll();
|
||||||
|
|
||||||
// helpers for writing values
|
// helpers for writing values
|
||||||
@@ -81,24 +74,10 @@ public:
|
|||||||
inline int putBool(const std::string &key, bool val) {
|
inline int putBool(const std::string &key, bool val) {
|
||||||
return put(key.c_str(), val ? "1" : "0", 1);
|
return put(key.c_str(), val ? "1" : "0", 1);
|
||||||
}
|
}
|
||||||
inline int putInt(const std::string &key, int val) {
|
|
||||||
return put(key.c_str(), std::to_string(val).c_str(), std::to_string(val).size());
|
|
||||||
}
|
|
||||||
inline int putFloat(const std::string &key, float val) {
|
|
||||||
return put(key.c_str(), std::to_string(val).c_str(), std::to_string(val).size());
|
|
||||||
}
|
|
||||||
void putNonBlocking(const std::string &key, const std::string &val);
|
void putNonBlocking(const std::string &key, const std::string &val);
|
||||||
inline void putBoolNonBlocking(const std::string &key, bool val) {
|
inline void putBoolNonBlocking(const std::string &key, bool val) {
|
||||||
putNonBlocking(key, val ? "1" : "0");
|
putNonBlocking(key, val ? "1" : "0");
|
||||||
}
|
}
|
||||||
void putIntNonBlocking(const std::string &key, const std::string &val);
|
|
||||||
inline void putIntNonBlocking(const std::string &key, int val) {
|
|
||||||
putNonBlocking(key, std::to_string(val));
|
|
||||||
}
|
|
||||||
void putFloatNonBlocking(const std::string &key, const std::string &val);
|
|
||||||
inline void putFloatNonBlocking(const std::string &key, float val) {
|
|
||||||
putNonBlocking(key, std::to_string(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void asyncWriteThread();
|
void asyncWriteThread();
|
||||||
|
|||||||
+1
-1
@@ -14,6 +14,6 @@ if __name__ == "__main__":
|
|||||||
if len(sys.argv) == 3:
|
if len(sys.argv) == 3:
|
||||||
val = sys.argv[2]
|
val = sys.argv[2]
|
||||||
print(f"SET: {key} = {val}")
|
print(f"SET: {key} = {val}")
|
||||||
params.put(key, val)
|
params.put(key, val, block=True)
|
||||||
elif len(sys.argv) == 2:
|
elif len(sys.argv) == 2:
|
||||||
print(f"GET: {key} = {params.get(key)}")
|
print(f"GET: {key} = {params.get(key)}")
|
||||||
|
|||||||
+189
-229
@@ -2,13 +2,12 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "cereal/gen/cpp/log.capnp.h"
|
#include "cereal/gen/cpp/log.capnp.h"
|
||||||
|
|
||||||
inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||||
{"AccessToken", {CLEAR_ON_MANAGER_START | DONT_LOG, STRING}},
|
{"AccessToken", {CLEAR_ON_MANAGER_START | DONT_LOG, STRING}},
|
||||||
{"AdbEnabled", {PERSISTENT, BOOL}},
|
{"AdbEnabled", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"AlwaysOnDM", {PERSISTENT, BOOL}},
|
{"AlwaysOnDM", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"ApiCache_Device", {PERSISTENT, STRING}},
|
{"ApiCache_Device", {PERSISTENT, STRING}},
|
||||||
{"ApiCache_FirehoseStats", {PERSISTENT, JSON}},
|
{"ApiCache_FirehoseStats", {PERSISTENT, JSON}},
|
||||||
{"AssistNowToken", {PERSISTENT, STRING}},
|
{"AssistNowToken", {PERSISTENT, STRING}},
|
||||||
@@ -29,36 +28,36 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"CurrentBootlog", {PERSISTENT, STRING}},
|
{"CurrentBootlog", {PERSISTENT, STRING}},
|
||||||
{"CurrentRoute", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, STRING}},
|
{"CurrentRoute", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, STRING}},
|
||||||
{"DisableLogging", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
{"DisableLogging", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"DisablePowerDown", {PERSISTENT, BOOL}},
|
{"DisablePowerDown", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"DisableUpdates", {PERSISTENT, BOOL}},
|
{"DisableUpdates", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"DisengageOnAccelerator", {PERSISTENT, BOOL, "0"}},
|
{"DisengageOnAccelerator", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"DongleId", {PERSISTENT, STRING}},
|
{"DongleId", {PERSISTENT, STRING}},
|
||||||
{"DoReboot", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"DoReboot", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"DoShutdown", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"DoShutdown", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"DoUninstall", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"DoUninstall", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"DriverTooDistracted", {CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON, BOOL}},
|
{"DriverTooDistracted", {CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON, BOOL}},
|
||||||
{"AlphaLongitudinalEnabled", {PERSISTENT | DEVELOPMENT_ONLY, BOOL}},
|
{"AlphaLongitudinalEnabled", {PERSISTENT | DEVELOPMENT_ONLY | BACKUP, BOOL}},
|
||||||
{"ExperimentalMode", {PERSISTENT, BOOL}},
|
{"ExperimentalMode", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"ExperimentalModeConfirmed", {PERSISTENT, BOOL}},
|
{"ExperimentalModeConfirmed", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"FirmwareQueryDone", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
{"FirmwareQueryDone", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"ForcePowerDown", {PERSISTENT, BOOL}},
|
{"ForcePowerDown", {PERSISTENT, BOOL}},
|
||||||
{"GitBranch", {PERSISTENT, STRING}},
|
{"GitBranch", {PERSISTENT, STRING}},
|
||||||
{"GitCommit", {PERSISTENT, STRING}},
|
{"GitCommit", {PERSISTENT, STRING}},
|
||||||
{"GitCommitDate", {PERSISTENT, STRING}},
|
{"GitCommitDate", {PERSISTENT, STRING}},
|
||||||
{"GitDiff", {PERSISTENT, STRING}},
|
{"GitDiff", {PERSISTENT, STRING}},
|
||||||
{"GithubSshKeys", {PERSISTENT, STRING}},
|
{"GithubSshKeys", {PERSISTENT | BACKUP, STRING}},
|
||||||
{"GithubUsername", {PERSISTENT, STRING}},
|
{"GithubUsername", {PERSISTENT | BACKUP, STRING}},
|
||||||
{"GitRemote", {PERSISTENT, STRING}},
|
{"GitRemote", {PERSISTENT, STRING}},
|
||||||
{"GsmApn", {PERSISTENT, STRING}},
|
{"GsmApn", {PERSISTENT | BACKUP, STRING}},
|
||||||
{"GsmMetered", {PERSISTENT, BOOL, "1"}},
|
{"GsmMetered", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"GsmRoaming", {PERSISTENT, BOOL}},
|
{"GsmRoaming", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"HardwareSerial", {PERSISTENT, STRING}},
|
{"HardwareSerial", {PERSISTENT, STRING}},
|
||||||
{"HasAcceptedTerms", {PERSISTENT, STRING, "0"}},
|
{"HasAcceptedTerms", {PERSISTENT, STRING, "0"}},
|
||||||
{"InstallDate", {PERSISTENT, TIME}},
|
{"InstallDate", {PERSISTENT, TIME}},
|
||||||
{"IsDriverViewEnabled", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"IsDriverViewEnabled", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"IsEngaged", {PERSISTENT, BOOL}},
|
{"IsEngaged", {PERSISTENT, BOOL}},
|
||||||
{"IsLdwEnabled", {PERSISTENT, BOOL}},
|
{"IsLdwEnabled", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"IsMetric", {PERSISTENT, BOOL}},
|
{"IsMetric", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"IsOffroad", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"IsOffroad", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"IsOnroad", {PERSISTENT, BOOL}},
|
{"IsOnroad", {PERSISTENT, BOOL}},
|
||||||
{"IsRhdDetected", {PERSISTENT, BOOL}},
|
{"IsRhdDetected", {PERSISTENT, BOOL}},
|
||||||
@@ -66,50 +65,56 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"IsTakingSnapshot", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"IsTakingSnapshot", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"IsTestedBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"IsTestedBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"JoystickDebugMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
{"JoystickDebugMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"LanguageSetting", {PERSISTENT, STRING, "en"}},
|
{"LanguageSetting", {PERSISTENT | BACKUP, STRING, "en"}},
|
||||||
{"LastAthenaPingTime", {CLEAR_ON_MANAGER_START, INT}},
|
{"LastAthenaPingTime", {CLEAR_ON_MANAGER_START, INT}},
|
||||||
{"LastGPSPosition", {PERSISTENT, STRING}},
|
{"LastGPSPosition", {PERSISTENT, STRING}},
|
||||||
{"LastManagerExitReason", {CLEAR_ON_MANAGER_START, STRING}},
|
{"LastManagerExitReason", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"LastOffroadStatusPacket", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, JSON}},
|
{"LastOffroadStatusPacket", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, JSON}},
|
||||||
|
{"LastAgnosPowerMonitorShutdown", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"LastPowerDropDetected", {CLEAR_ON_MANAGER_START, STRING}},
|
{"LastPowerDropDetected", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"LastUpdateException", {CLEAR_ON_MANAGER_START, STRING}},
|
{"LastUpdateException", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
|
{"LastUpdateRouteCount", {PERSISTENT, INT, "0"}},
|
||||||
{"LastUpdateTime", {PERSISTENT, TIME}},
|
{"LastUpdateTime", {PERSISTENT, TIME}},
|
||||||
{"LiveDelay", {PERSISTENT, BYTES}},
|
{"LastUpdateUptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||||
|
{"LiveDelay", {PERSISTENT | BACKUP, BYTES}},
|
||||||
{"LiveParameters", {PERSISTENT, JSON}},
|
{"LiveParameters", {PERSISTENT, JSON}},
|
||||||
{"LiveParametersV2", {PERSISTENT, BYTES}},
|
{"LiveParametersV2", {PERSISTENT, BYTES}},
|
||||||
|
{"LivestreamEncoderBitrate", {CLEAR_ON_MANAGER_START | DONT_LOG, INT}},
|
||||||
{"LiveTorqueParameters", {PERSISTENT | DONT_LOG, BYTES}},
|
{"LiveTorqueParameters", {PERSISTENT | DONT_LOG, BYTES}},
|
||||||
{"LocationFilterInitialState", {PERSISTENT, BYTES}},
|
{"LocationFilterInitialState", {PERSISTENT, BYTES}},
|
||||||
|
{"LateralManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"LongitudinalManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
{"LongitudinalManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"LongitudinalPersonality", {PERSISTENT, INT, std::to_string(static_cast<int>(cereal::LongitudinalPersonality::STANDARD))}},
|
{"LongitudinalPersonality", {PERSISTENT | BACKUP, INT, std::to_string(static_cast<int>(cereal::LongitudinalPersonality::STANDARD))}},
|
||||||
{"NetworkMetered", {PERSISTENT, BOOL}},
|
{"NetworkMetered", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"ObdMultiplexingChanged", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
{"ObdMultiplexingChanged", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"ObdMultiplexingEnabled", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
{"ObdMultiplexingEnabled", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"Offroad_BadNvme", {CLEAR_ON_MANAGER_START, BOOL}},
|
|
||||||
{"Offroad_CarUnrecognized", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
{"Offroad_CarUnrecognized", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"Offroad_ConnectivityNeeded", {CLEAR_ON_MANAGER_START, JSON}},
|
{"Offroad_ConnectivityNeeded", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_ConnectivityNeededPrompt", {CLEAR_ON_MANAGER_START, JSON}},
|
{"Offroad_ConnectivityNeededPrompt", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
|
{"Offroad_ExcessiveActuation", {PERSISTENT, JSON}},
|
||||||
{"Offroad_IsTakingSnapshot", {CLEAR_ON_MANAGER_START, JSON}},
|
{"Offroad_IsTakingSnapshot", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_NeosUpdate", {CLEAR_ON_MANAGER_START, JSON}},
|
{"Offroad_NeosUpdate", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_NoFirmware", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
{"Offroad_NoFirmware", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"Offroad_Recalibration", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
{"Offroad_Recalibration", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"Offroad_StorageMissing", {CLEAR_ON_MANAGER_START, BOOL}},
|
|
||||||
{"Offroad_TemperatureTooHigh", {CLEAR_ON_MANAGER_START, JSON}},
|
{"Offroad_TemperatureTooHigh", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_UnofficialHardware", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"Offroad_UnregisteredHardware", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_UpdateFailed", {CLEAR_ON_MANAGER_START, JSON}},
|
{"Offroad_UpdateFailed", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_DriverMonitoringUncertain", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
{"Offroad_DriverMonitoringUncertain", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"OpenpilotEnabledToggle", {PERSISTENT, BOOL, "1"}},
|
{"OnroadCycleRequested", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
|
{"OpenpilotEnabledToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"PandaHeartbeatLost", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
{"PandaHeartbeatLost", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"PandaSomResetTriggered", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
|
||||||
{"PandaSignatures", {CLEAR_ON_MANAGER_START, BYTES}},
|
|
||||||
{"PrimeType", {PERSISTENT, INT}},
|
{"PrimeType", {PERSISTENT, INT}},
|
||||||
{"RecordAudio", {PERSISTENT, BOOL}},
|
{"RecordAudio", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"RecordFront", {PERSISTENT, BOOL}},
|
{"RecordAudioFeedback", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"RecordFront", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"RecordFrontLock", {PERSISTENT, BOOL}}, // for the internal fleet
|
{"RecordFrontLock", {PERSISTENT, BOOL}}, // for the internal fleet
|
||||||
{"SecOCKey", {PERSISTENT | DONT_LOG, STRING}},
|
{"SecOCKey", {PERSISTENT | DONT_LOG | BACKUP, STRING}},
|
||||||
|
{"ShowDebugInfo", {PERSISTENT, BOOL}},
|
||||||
{"RouteCount", {PERSISTENT, INT, "0"}},
|
{"RouteCount", {PERSISTENT, INT, "0"}},
|
||||||
{"SnoozeUpdate", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
{"SnoozeUpdate", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"SshEnabled", {PERSISTENT, BOOL}},
|
{"SshEnabled", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"TermsVersion", {PERSISTENT, STRING}},
|
{"TermsVersion", {PERSISTENT, STRING}},
|
||||||
|
{"TorqueBar", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"TrainingVersion", {PERSISTENT, STRING}},
|
{"TrainingVersion", {PERSISTENT, STRING}},
|
||||||
{"UbloxAvailable", {PERSISTENT, BOOL}},
|
{"UbloxAvailable", {PERSISTENT, BOOL}},
|
||||||
{"UpdateAvailable", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
{"UpdateAvailable", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
@@ -123,217 +128,172 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"UpdaterState", {CLEAR_ON_MANAGER_START, STRING}},
|
{"UpdaterState", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"UpdaterTargetBranch", {CLEAR_ON_MANAGER_START, STRING}},
|
{"UpdaterTargetBranch", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"UpdaterLastFetchTime", {PERSISTENT, TIME}},
|
{"UpdaterLastFetchTime", {PERSISTENT, TIME}},
|
||||||
|
{"UptimeOffroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||||
|
{"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||||
|
{"UsbGpuPresent", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
|
{"UsbGpuCompiled", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"Version", {PERSISTENT, STRING}},
|
{"Version", {PERSISTENT, STRING}},
|
||||||
|
|
||||||
|
// --- infiniteCable params --- //
|
||||||
|
{"DisableScreenTimer", {PERSISTENT, BOOL}},
|
||||||
|
{"DarkMode", {PERSISTENT, BOOL}},
|
||||||
|
{"EnableCurvatureController", {PERSISTENT, BOOL, "1"}},
|
||||||
|
{"EnableCurvatureD", {PERSISTENT, BOOL, "0"}},
|
||||||
|
{"CurvatureDDebugData", {PERSISTENT, BOOL, "0"}},
|
||||||
|
{"EnableLongComfortMode", {PERSISTENT, BOOL}},
|
||||||
|
{"EnableSmoothSteer", {PERSISTENT, BOOL}},
|
||||||
|
{"EnableSpeedLimitControl", {PERSISTENT, BOOL}},
|
||||||
|
{"EnableSpeedLimitPredicative", {PERSISTENT, BOOL}},
|
||||||
|
{"EnableSLPredReactToSL", {PERSISTENT, BOOL}},
|
||||||
|
{"EnableSLPredReactToCurves", {PERSISTENT, BOOL}},
|
||||||
|
{"BatteryDetails", {PERSISTENT, BOOL}},
|
||||||
|
{"ShowDynamicSteeringLearnerGraph", {PERSISTENT, BOOL}},
|
||||||
|
{"ForceRHDForBSM", {PERSISTENT, BOOL}},
|
||||||
|
{"DisableCarSteerAlerts", {PERSISTENT, BOOL}},
|
||||||
|
{"ShowAccelBar", {PERSISTENT, BOOL}},
|
||||||
|
{"LiveCurvatureParameters", {PERSISTENT | DONT_LOG, BYTES}},
|
||||||
|
|
||||||
// carrot
|
// --- sunnypilot params --- //
|
||||||
{"LongitudinalPersonalityMax", {PERSISTENT, INT, "3"}},
|
{"ApiCache_DriveStats", {PERSISTENT, JSON}},
|
||||||
{"NetworkAddress", {CLEAR_ON_MANAGER_START, STRING}},
|
{"AutoLaneChangeBsmDelay", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"AutoLaneChangeTimer", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"BlinkerLateralReengageDelay", {PERSISTENT | BACKUP, INT, "0"}}, // seconds
|
||||||
|
{"BlinkerMinLateralControlSpeed", {PERSISTENT | BACKUP, INT, "20"}}, // MPH or km/h
|
||||||
|
{"BlinkerPauseLateralControl", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"Brightness", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"CarList", {PERSISTENT, JSON}},
|
||||||
|
{"CarParamsSP", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BYTES}},
|
||||||
|
{"CarParamsSPCache", {CLEAR_ON_MANAGER_START, BYTES}},
|
||||||
|
{"CarParamsSPPersistent", {PERSISTENT, BYTES}},
|
||||||
|
{"CarPlatformBundle", {PERSISTENT | BACKUP, JSON}},
|
||||||
|
{"ChevronInfo", {PERSISTENT | BACKUP, INT, "4"}},
|
||||||
|
{"CompletedSunnylinkConsentVersion", {PERSISTENT, STRING, "0"}},
|
||||||
|
{"CustomAccIncrementsEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"CustomAccLongPressIncrement", {PERSISTENT | BACKUP, INT, "5"}},
|
||||||
|
{"CustomAccShortPressIncrement", {PERSISTENT | BACKUP, INT, "1"}},
|
||||||
|
{"DeviceBootMode", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"DevUIInfo", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}},
|
||||||
|
{"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}},
|
||||||
|
{"GreenLightAlert", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}},
|
||||||
|
{"HasAcceptedTermsSP", {PERSISTENT, STRING, "0"}},
|
||||||
|
{"HideVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"IntelligentCruiseButtonManagement", {PERSISTENT | BACKUP , BOOL}},
|
||||||
|
{"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"IsDevelopmentBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
|
{"IsReleaseSpBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
|
{"LastGPSPositionLLK", {PERSISTENT, STRING}},
|
||||||
|
{"LeadDepartAlert", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"MaxTimeOffroad", {PERSISTENT | BACKUP, INT, "1800"}},
|
||||||
|
{"ModelRunnerTypeCache", {CLEAR_ON_ONROAD_TRANSITION, INT}},
|
||||||
|
{"OffroadMode", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
|
{"Offroad_TiciSupport", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
|
{"OnroadScreenOffBrightness", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"OnroadScreenOffBrightnessMigrated", {PERSISTENT | BACKUP, STRING, "0.0"}},
|
||||||
|
{"OnroadScreenOffTimer", {PERSISTENT | BACKUP, INT, "15"}},
|
||||||
|
{"OnroadScreenOffTimerMigrated", {PERSISTENT | BACKUP, STRING, "0.0"}},
|
||||||
|
{"OnroadUploads", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
|
{"QuickBootToggle", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"RocketFuel", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"ShowTurnSignals", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"TrueVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
{"ApiCache_NavDestinations", {PERSISTENT, STRING}},
|
// MADS params
|
||||||
{"NavDestination", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, STRING}},
|
{"Mads", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"NavDestinationWaypoints", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, STRING}},
|
{"MadsMainCruiseAllowed", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"NavPastDestinations", {PERSISTENT, STRING}},
|
{"MadsSteeringMode", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
{"NavSettingLeftSide", {PERSISTENT, BOOL}},
|
{"MadsUnifiedEngagementMode", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"NavSettingTime24h", {PERSISTENT, BOOL}},
|
|
||||||
{"MapboxStyle", {PERSISTENT, INT}},
|
|
||||||
{"MapboxPublicKey", {PERSISTENT, STRING}},
|
|
||||||
{"MapboxSecretKey", {PERSISTENT, STRING}},
|
|
||||||
{"GMapKey", {PERSISTENT, STRING}},
|
|
||||||
{"SearchInput", {PERSISTENT, INT}},
|
|
||||||
|
|
||||||
{"CarSelected3", {PERSISTENT, STRING, "MOCK"}},
|
// Model Manager params
|
||||||
{"SupportedCars", {PERSISTENT, STRING}},
|
{"ModelManager_ActiveBundle", {PERSISTENT, JSON}},
|
||||||
{"SupportedCars_gm", {PERSISTENT, STRING}},
|
{"ModelManager_ClearCache", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"ShowDebugUI", {PERSISTENT, INT, "0"}},
|
{"ModelManager_DownloadIndex", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, INT}},
|
||||||
{"ShowTpms", {PERSISTENT, INT, "1"}},
|
{"ModelManager_Favs", {PERSISTENT | BACKUP, STRING}},
|
||||||
{"ShowDateTime", {PERSISTENT, INT, "1"}},
|
{"ModelManager_LastSyncTime", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, INT, "0"}},
|
||||||
{"ShowPathEnd", {PERSISTENT, INT, "1"}},
|
{"ModelManager_ModelsCache", {PERSISTENT | BACKUP, JSON}},
|
||||||
{"ShowCustomBrightness", {PERSISTENT, INT, "100"}},
|
|
||||||
{"ShowLaneInfo", {PERSISTENT, INT, "1"}},
|
|
||||||
{"ShowRadarInfo", {PERSISTENT, INT, "1"}},
|
|
||||||
{"ShowDeviceState", {PERSISTENT, INT, "1"}},
|
|
||||||
{"ShowRouteInfo", {PERSISTENT, INT, "1"}},
|
|
||||||
{"ShowPathMode", {PERSISTENT, INT, "9"}},
|
|
||||||
{"ShowPathColor", {PERSISTENT, INT, "13"}},
|
|
||||||
{"ShowPathColorCruiseOff", {PERSISTENT, INT, "19"}},
|
|
||||||
{"ShowPathModeLane", {PERSISTENT, INT, "14"}},
|
|
||||||
{"ShowPathColorLane", {PERSISTENT, INT, "13"}},
|
|
||||||
{"ShowPlotMode", {PERSISTENT, INT, "0"}},
|
|
||||||
{"RecordRoadCam", {PERSISTENT, INT, "0"}},
|
|
||||||
{"HDPuse", {PERSISTENT, INT, "0"}},
|
|
||||||
|
|
||||||
{"AutoCruiseControl", {PERSISTENT, INT, "0"}},
|
// Neural Network Lateral Control
|
||||||
{"CruiseEcoControl", {PERSISTENT, INT, "2"}},
|
{"NeuralNetworkLateralControl", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"CarrotCruiseDecel", {PERSISTENT, INT, "-1"}},
|
|
||||||
{"CarrotCruiseAtcDecel", {PERSISTENT, INT, "-1"}},
|
|
||||||
{"CommaLongAcc", {PERSISTENT, INT, "0"}},
|
|
||||||
|
|
||||||
{"AutoGasTokSpeed", {PERSISTENT, INT, "0"}},
|
// sunnylink params
|
||||||
{"AutoGasSyncSpeed", {PERSISTENT, INT, "1"}},
|
{"EnableSunnylinkUploader", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"AutoEngage", {PERSISTENT, INT, "0"}},
|
{"LastSunnylinkPingTime", {CLEAR_ON_MANAGER_START, INT}},
|
||||||
{"DisableMinSteerSpeed", {PERSISTENT, INT, "0"}},
|
{"ParamsVersion", {PERSISTENT, INT}},
|
||||||
{"AutoCurveSpeedLowerLimit", {PERSISTENT, INT, "30"}},
|
{"SunnylinkCache_Roles", {PERSISTENT, STRING}},
|
||||||
{"AutoCurveSpeedFactor", {PERSISTENT, INT, "120"}},
|
{"SunnylinkCache_Users", {PERSISTENT, STRING}},
|
||||||
{"AutoCurveSpeedAggressiveness", {PERSISTENT, INT, "100"}},
|
{"SunnylinkDongleId", {PERSISTENT, STRING}},
|
||||||
|
{"SunnylinkdPid", {PERSISTENT, INT}},
|
||||||
|
{"SunnylinkEnabled", {PERSISTENT, BOOL, "1"}},
|
||||||
|
{"SunnylinkTempFault", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL, "0"}},
|
||||||
|
|
||||||
{"AutoTurnControl", {PERSISTENT, INT, "0"}},
|
// Backup Manager params
|
||||||
{"AutoTurnControlSpeedTurn", {PERSISTENT, INT, "20"}},
|
{"BackupManager_CreateBackup", {PERSISTENT, BOOL}},
|
||||||
{"AutoTurnControlTurnEnd", {PERSISTENT, INT, "6"}},
|
{"BackupManager_RestoreVersion", {PERSISTENT, STRING}},
|
||||||
{"AutoTurnMapChange", {PERSISTENT, INT, "0"}},
|
|
||||||
|
|
||||||
{"AutoNaviSpeedCtrlEnd", {PERSISTENT, INT, "7"}},
|
// sunnypilot car specific params
|
||||||
{"AutoNaviSpeedCtrlMode", {PERSISTENT, INT, "2"}},
|
{"HyundaiLongitudinalTuning", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
{"AutoRoadSpeedLimitOffset", {PERSISTENT, INT, "-1"}},
|
{"SubaruStopAndGo", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"AutoNaviSpeedBumpTime", {PERSISTENT, INT, "1"}},
|
{"SubaruStopAndGoManualParkingBrake", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"AutoNaviSpeedBumpSpeed", {PERSISTENT, INT, "35"}},
|
{"TeslaCoopSteering", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"AutoNaviSpeedDecelRate", {PERSISTENT, INT, "120"}},
|
{"ToyotaEnforceStockLongitudinal", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"AutoNaviSpeedSafetyFactor", {PERSISTENT, INT, "105"}},
|
{"ToyotaStopAndGoHack", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"AutoNaviCountDownMode", {PERSISTENT, INT, "2"}},
|
|
||||||
{"TurnSpeedControlMode", {PERSISTENT, INT, "1"}},
|
|
||||||
|
|
||||||
{"CarrotSmartSpeedControl", {PERSISTENT, INT, "0"}},
|
{"DynamicExperimentalControl", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"MapTurnSpeedFactor", {PERSISTENT, INT, "90"}},
|
{"BlindSpot", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"ModelTurnSpeedFactor", {PERSISTENT, INT, "0"}},
|
|
||||||
{"StoppingAccel", {PERSISTENT, INT, "0"}},
|
|
||||||
{"AutoSpeedUptoRoadSpeedLimit", {PERSISTENT, INT, "0"}},
|
|
||||||
{"AutoRoadSpeedAdjust", {PERSISTENT, INT, "50"}},
|
|
||||||
|
|
||||||
{"StopDistanceCarrot", {PERSISTENT, INT, "550"}},
|
// sunnypilot model params
|
||||||
{"JLeadFactor3", {PERSISTENT, INT, "0"}},
|
{"CameraOffset", {PERSISTENT | BACKUP, FLOAT, "0.0"}},
|
||||||
{"CruiseButtonMode", {PERSISTENT, INT, "0"}},
|
{"LagdToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"CancelButtonMode", {PERSISTENT, INT, "0"}},
|
{"LagdToggleDelay", {PERSISTENT | BACKUP, FLOAT, "0.2"}},
|
||||||
{"LfaButtonMode", {PERSISTENT, INT, "0"}},
|
{"LagdValueCache", {PERSISTENT, FLOAT, "0.2"}},
|
||||||
{"CruiseButtonTest1", {PERSISTENT, INT, "8"}},
|
{"LaneTurnDesire", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"CruiseButtonTest2", {PERSISTENT, INT, "30"}},
|
{"LaneTurnValue", {PERSISTENT | BACKUP, FLOAT, "19.0"}},
|
||||||
{"CruiseButtonTest3", {PERSISTENT, INT, "1"}},
|
{"PlanplusControl", {PERSISTENT | BACKUP, FLOAT, "1.0"}},
|
||||||
|
|
||||||
{"CruiseSpeedUnit", {PERSISTENT, INT, "10"}},
|
// mapd
|
||||||
{"CruiseSpeedUnitBasic", {PERSISTENT, INT, "1"}},
|
{"MapAdvisorySpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, FLOAT}},
|
||||||
{"CruiseSpeed1", {PERSISTENT, INT, "30"}},
|
{"MapdVersion", {PERSISTENT, STRING}},
|
||||||
{"CruiseSpeed2", {PERSISTENT, INT, "50"}},
|
{"MapSpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, FLOAT, "0.0"}},
|
||||||
{"CruiseSpeed3", {PERSISTENT, INT, "80"}},
|
{"NextMapSpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"CruiseSpeed4", {PERSISTENT, INT, "110"}},
|
{"Offroad_OSMUpdateRequired", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"CruiseSpeed5", {PERSISTENT, INT, "130"}},
|
{"OsmDbUpdatesCheck", {CLEAR_ON_MANAGER_START, BOOL}}, // mapd database update happens with device ON, reset on boot
|
||||||
|
{"OSMDownloadBounds", {PERSISTENT, STRING}},
|
||||||
|
{"OsmDownloadedDate", {PERSISTENT, STRING, "0.0"}},
|
||||||
|
{"OSMDownloadLocations", {PERSISTENT, JSON}},
|
||||||
|
{"OSMDownloadProgress", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
|
{"OsmLocal", {PERSISTENT, BOOL}},
|
||||||
|
{"OsmLocationName", {PERSISTENT, STRING}},
|
||||||
|
{"OsmLocationTitle", {PERSISTENT, STRING}},
|
||||||
|
{"OsmLocationUrl", {PERSISTENT, STRING}},
|
||||||
|
{"OsmStateName", {PERSISTENT, STRING, "All"}},
|
||||||
|
{"OsmStateTitle", {PERSISTENT, STRING}},
|
||||||
|
{"OsmWayTest", {PERSISTENT, STRING}},
|
||||||
|
{"RoadName", {CLEAR_ON_ONROAD_TRANSITION, STRING}},
|
||||||
|
{"RoadNameToggle", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
{"PaddleMode", {PERSISTENT, INT, "0"}},
|
// Speed Limit
|
||||||
{"MyDrivingMode", {PERSISTENT, INT, "3"}},
|
{"SpeedLimitMode", {PERSISTENT | BACKUP, INT, "1"}},
|
||||||
{"MyDrivingModeAuto", {PERSISTENT, INT, "0"}},
|
{"SpeedLimitOffsetType", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
{"TrafficLightDetectMode", {PERSISTENT, INT, "2"}},
|
{"SpeedLimitPolicy", {PERSISTENT | BACKUP, INT, "3"}},
|
||||||
|
{"SpeedLimitValueOffset", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
|
||||||
{"SteerActuatorDelay", {PERSISTENT, INT, "0"}},
|
// Smart Cruise Control
|
||||||
{"LatSmoothSec", {PERSISTENT, INT, "13"}},
|
{"MapTargetVelocities", {CLEAR_ON_ONROAD_TRANSITION, STRING}},
|
||||||
{"LatSuspendAngleDeg", {PERSISTENT, INT, "300"}},
|
{"SmartCruiseControlMap", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"CruiseOnDist", {PERSISTENT, INT, "400"}},
|
{"SmartCruiseControlVision", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
{"CruiseMaxVals0", {PERSISTENT, INT, "160"}},
|
// Torque lateral control custom params
|
||||||
{"CruiseMaxVals1", {PERSISTENT, INT, "200"}},
|
{"CustomTorqueParams", {PERSISTENT | BACKUP , BOOL}},
|
||||||
{"CruiseMaxVals2", {PERSISTENT, INT, "160"}},
|
{"EnforceTorqueControl", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"CruiseMaxVals3", {PERSISTENT, INT, "130"}},
|
{"LiveTorqueParamsToggle", {PERSISTENT | BACKUP , BOOL}},
|
||||||
{"CruiseMaxVals4", {PERSISTENT, INT, "110"}},
|
{"LiveTorqueParamsRelaxedToggle", {PERSISTENT | BACKUP , BOOL}},
|
||||||
{"CruiseMaxVals5", {PERSISTENT, INT, "95"}},
|
{"TorqueControlTune", {PERSISTENT | BACKUP, FLOAT, "0.0"}},
|
||||||
{"CruiseMaxVals6", {PERSISTENT, INT, "80"}},
|
{"TorqueParamsOverrideEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"TorqueParamsOverrideFriction", {PERSISTENT | BACKUP, FLOAT, "0.1"}},
|
||||||
{"LongTuningKpV", {PERSISTENT, INT, "100"}},
|
{"TorqueParamsOverrideLatAccelFactor", {PERSISTENT | BACKUP, FLOAT, "2.5"}},
|
||||||
{"LongTuningKiV", {PERSISTENT, INT, "0"}},
|
|
||||||
{"LongTuningKf", {PERSISTENT, INT, "100"}},
|
|
||||||
{"LongActuatorDelay", {PERSISTENT, INT, "20"}},
|
|
||||||
{"VEgoStopping", {PERSISTENT, INT, "50"}},
|
|
||||||
|
|
||||||
{"RadarReactionFactor", {PERSISTENT, INT, "100"}},
|
|
||||||
{"EnableRadarTracks", {PERSISTENT, INT, "0"}},
|
|
||||||
{"RadarLatFactor", {PERSISTENT, INT, "0"}},
|
|
||||||
{"EnableCornerRadar", {PERSISTENT, INT, "0"}},
|
|
||||||
|
|
||||||
{"EnableRadarTracksResult", {PERSISTENT | CLEAR_ON_MANAGER_START, INT}},
|
|
||||||
{"CanParserResult", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, STRING}},
|
|
||||||
|
|
||||||
{"HotspotOnBoot", {PERSISTENT, INT, "0"}},
|
|
||||||
{"SoftwareMenu", {PERSISTENT, INT, "1"}},
|
|
||||||
|
|
||||||
{"HyundaiCameraSCC", {PERSISTENT, INT, "0"}},
|
|
||||||
{"FingerPrints", {PERSISTENT | CLEAR_ON_MANAGER_START, STRING}},
|
|
||||||
{"IsLdwsCar", {PERSISTENT, INT, "0"}},
|
|
||||||
{"CanfdHDA2", {PERSISTENT, INT, "0"}},
|
|
||||||
{"CanfdDebug", {PERSISTENT, INT, "0"}},
|
|
||||||
|
|
||||||
{"SoundVolumeAdjust", {PERSISTENT, INT, "100"}},
|
|
||||||
{"SoundVolumeAdjustEngage", {PERSISTENT, INT, "10"}},
|
|
||||||
|
|
||||||
{"TFollowGap1", {PERSISTENT, INT, "110"}},
|
|
||||||
{"TFollowGap2", {PERSISTENT, INT, "120"}},
|
|
||||||
{"TFollowGap3", {PERSISTENT, INT, "140"}},
|
|
||||||
{"TFollowGap4", {PERSISTENT, INT, "160"}},
|
|
||||||
|
|
||||||
{"DynamicTFollow", {PERSISTENT, INT, "0"}},
|
|
||||||
{"DynamicTFollowLC", {PERSISTENT, INT, "100"}},
|
|
||||||
{"EnableSpeedTF", {PERSISTENT, INT, "0"}},
|
|
||||||
{"AChangeCostStarting", {PERSISTENT, INT, "10"}},
|
|
||||||
{"TrafficStopDistanceAdjust", {PERSISTENT, INT, "400"}},
|
|
||||||
|
|
||||||
{"HapticFeedbackWhenSpeedCamera", {PERSISTENT, INT, "0"}},
|
|
||||||
{"UseLaneLineSpeed", {PERSISTENT, INT, "0"}},
|
|
||||||
{"UseLaneLineCurveSpeed", {PERSISTENT, INT, "0"}},
|
|
||||||
|
|
||||||
{"AdjustLaneOffset", {PERSISTENT, INT, "0"}},
|
|
||||||
{"LaneChangeNeedTorque", {PERSISTENT, INT, "0"}},
|
|
||||||
{"LaneChangeDelay", {PERSISTENT, INT, "0"}},
|
|
||||||
{"LaneChangeBsd", {PERSISTENT, INT, "0"}},
|
|
||||||
{"MaxAngleFrames", {PERSISTENT, INT, "89"}},
|
|
||||||
|
|
||||||
{"SoftHoldMode", {PERSISTENT, INT, "0"}},
|
|
||||||
|
|
||||||
{"LatMpcPathCost", {PERSISTENT, INT, "200"}},
|
|
||||||
{"LatMpcMotionCost", {PERSISTENT, INT, "7"}},
|
|
||||||
{"LatMpcAccelCost", {PERSISTENT, INT, "120"}},
|
|
||||||
{"LatMpcJerkCost", {PERSISTENT, INT, "4"}},
|
|
||||||
{"LatMpcSteeringRateCost", {PERSISTENT, INT, "7"}},
|
|
||||||
{"LatMpcInputOffset", {PERSISTENT, INT, "4"}},
|
|
||||||
|
|
||||||
{"PathOffset", {PERSISTENT, INT, "0"}},
|
|
||||||
|
|
||||||
{"LateralTorqueCustom", {PERSISTENT, INT, "0"}},
|
|
||||||
{"LateralTorqueAccelFactor", {PERSISTENT, INT, "2500"}},
|
|
||||||
{"LateralTorqueFriction", {PERSISTENT, INT, "100"}},
|
|
||||||
{"LateralTorqueKpV", {PERSISTENT, INT, "100"}},
|
|
||||||
{"LateralTorqueKiV", {PERSISTENT, INT, "10"}},
|
|
||||||
{"LateralTorqueKf", {PERSISTENT, INT, "100"}},
|
|
||||||
{"LateralTorqueKd", {PERSISTENT, INT, "0"}},
|
|
||||||
|
|
||||||
{"CustomSteerMax", {PERSISTENT, INT, "0"}},
|
|
||||||
{"CustomSteerDeltaUp", {PERSISTENT, INT, "0"}},
|
|
||||||
{"CustomSteerDeltaDown", {PERSISTENT, INT, "0"}},
|
|
||||||
{"CustomSteerDeltaUpLC", {PERSISTENT, INT, "0"}},
|
|
||||||
{"CustomSteerDeltaDownLC", {PERSISTENT, INT, "0"}},
|
|
||||||
|
|
||||||
{"SpeedFromPCM", {PERSISTENT, INT, "2"}},
|
|
||||||
{"MaxTimeOffroadMin", {PERSISTENT, INT, "60"}},
|
|
||||||
|
|
||||||
{"DisableDM", {PERSISTENT, INT, "0"}},
|
|
||||||
{"EnableConnect", {PERSISTENT, INT, "0"}},
|
|
||||||
{"MuteDoor", {PERSISTENT, INT, "0"}},
|
|
||||||
{"MuteSeatbelt", {PERSISTENT, INT, "0"}},
|
|
||||||
|
|
||||||
{"CarrotException", {CLEAR_ON_MANAGER_START, STRING}},
|
|
||||||
|
|
||||||
{"CarrotSpeed", {PERSISTENT, INT} },
|
|
||||||
{"CarrotSpeedViz", {PERSISTENT, JSON} },
|
|
||||||
{"CarrotSpeedTable", {PERSISTENT, BYTES} },
|
|
||||||
{"CarName", {PERSISTENT, STRING}},
|
|
||||||
{"EVTable", {PERSISTENT, BOOL, "0"}},
|
|
||||||
{"LongPitch", {PERSISTENT, BOOL, "0"}},
|
|
||||||
|
|
||||||
{"ActivateCruiseAfterBrake", {CLEAR_ON_MANAGER_START, INT, "0"}},
|
|
||||||
|
|
||||||
{"CustomSR", {PERSISTENT, INT, "0"}},
|
|
||||||
{"SteerRatioRate", {PERSISTENT, INT, "100"}},
|
|
||||||
|
|
||||||
{"SoftRestartTriggered", {CLEAR_ON_MANAGER_START, INT}},
|
|
||||||
|
|
||||||
{"DevicePosition", {CLEAR_ON_MANAGER_START, STRING}},
|
|
||||||
{"NNFF", {PERSISTENT, INT, "0"}},
|
|
||||||
{"NNFFLite", {PERSISTENT, INT, "0"}},
|
|
||||||
{"NNFFModelName", {CLEAR_ON_OFFROAD_TRANSITION, STRING}},
|
|
||||||
|
|
||||||
{"HardwareC3xLite", {PERSISTENT, INT, "0"}},
|
|
||||||
{"ShareData", {PERSISTENT, INT, "0"}},
|
|
||||||
};
|
};
|
||||||
|
|||||||
+17
-61
@@ -18,6 +18,7 @@ cdef extern from "common/params.h":
|
|||||||
CLEAR_ON_OFFROAD_TRANSITION
|
CLEAR_ON_OFFROAD_TRANSITION
|
||||||
DEVELOPMENT_ONLY
|
DEVELOPMENT_ONLY
|
||||||
CLEAR_ON_IGNITION_ON
|
CLEAR_ON_IGNITION_ON
|
||||||
|
BACKUP
|
||||||
ALL
|
ALL
|
||||||
|
|
||||||
cpdef enum ParamKeyType:
|
cpdef enum ParamKeyType:
|
||||||
@@ -33,23 +34,17 @@ cdef extern from "common/params.h":
|
|||||||
c_Params(string) except + nogil
|
c_Params(string) except + nogil
|
||||||
string get(string, bool) nogil
|
string get(string, bool) nogil
|
||||||
bool getBool(string, bool) nogil
|
bool getBool(string, bool) nogil
|
||||||
int getInt(string, bool) nogil
|
|
||||||
float getFloat(string, bool) nogil
|
|
||||||
int remove(string) nogil
|
int remove(string) nogil
|
||||||
int put(string, string) nogil
|
int put(string, string) nogil
|
||||||
void putNonBlocking(string, string) nogil
|
void putNonBlocking(string, string) nogil
|
||||||
void putBoolNonBlocking(string, bool) nogil
|
void putBoolNonBlocking(string, bool) nogil
|
||||||
void putIntNonBlocking(string, int) nogil
|
|
||||||
void putFloatNonBlocking(string, float) nogil
|
|
||||||
int putBool(string, bool) nogil
|
int putBool(string, bool) nogil
|
||||||
int putInt(string, int) nogil
|
|
||||||
int putFloat(string, float) nogil
|
|
||||||
bool checkKey(string) nogil
|
bool checkKey(string) nogil
|
||||||
ParamKeyType getKeyType(string) nogil
|
ParamKeyType getKeyType(string) nogil
|
||||||
optional[string] getKeyDefaultValue(string) nogil
|
optional[string] getKeyDefaultValue(string) nogil
|
||||||
string getParamPath(string) nogil
|
string getParamPath(string) nogil
|
||||||
void clearAll(ParamKeyFlag)
|
void clearAll(ParamKeyFlag)
|
||||||
vector[string] allKeys()
|
vector[string] allKeys(ParamKeyFlag)
|
||||||
|
|
||||||
PYTHON_2_CPP = {
|
PYTHON_2_CPP = {
|
||||||
(str, STRING): lambda v: v,
|
(str, STRING): lambda v: v,
|
||||||
@@ -147,67 +142,28 @@ cdef class Params:
|
|||||||
cdef ParamKeyType t = self.p.getKeyType(k)
|
cdef ParamKeyType t = self.p.getKeyType(k)
|
||||||
return ensure_bytes(self.python2cpp(type(dat), t, dat, key))
|
return ensure_bytes(self.python2cpp(type(dat), t, dat, key))
|
||||||
|
|
||||||
def get_int(self, key, bool block=False):
|
def put(self, key, dat, bool block = False):
|
||||||
cdef string k = self.check_key(key)
|
|
||||||
cdef int r
|
|
||||||
with nogil:
|
|
||||||
r = self.p.getInt(k, block)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def get_float(self, key, bool block=False):
|
|
||||||
cdef string k = self.check_key(key)
|
|
||||||
cdef float r
|
|
||||||
with nogil:
|
|
||||||
r = self.p.getFloat(k, block)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def put(self, key, dat):
|
|
||||||
"""
|
"""
|
||||||
Warning: This function blocks until the param is written to disk!
|
Warning: block=True blocks until the param is written to disk!
|
||||||
In very rare cases this can take over a second, and your code will hang.
|
In very rare cases this can take over a second, and your code will hang.
|
||||||
Use the put_nonblocking, put_bool_nonblocking in time sensitive code, but
|
Use block=False in time sensitive code, but in general try to avoid
|
||||||
in general try to avoid writing params as much as possible.
|
writing params as much as possible.
|
||||||
"""
|
"""
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
cdef string dat_bytes = self._put_cast(key, dat)
|
cdef string dat_bytes = self._put_cast(key, dat)
|
||||||
with nogil:
|
with nogil:
|
||||||
self.p.put(k, dat_bytes)
|
if block:
|
||||||
|
self.p.put(k, dat_bytes)
|
||||||
|
else:
|
||||||
|
self.p.putNonBlocking(k, dat_bytes)
|
||||||
|
|
||||||
def put_bool(self, key, bool val):
|
def put_bool(self, key, bool val, bool block = False):
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
with nogil:
|
with nogil:
|
||||||
self.p.putBool(k, val)
|
if block:
|
||||||
|
self.p.putBool(k, val)
|
||||||
def put_int(self, key, int val):
|
else:
|
||||||
cdef string k = self.check_key(key)
|
self.p.putBoolNonBlocking(k, val)
|
||||||
with nogil:
|
|
||||||
self.p.putInt(k, val)
|
|
||||||
|
|
||||||
def put_float(self, key, float val):
|
|
||||||
cdef string k = self.check_key(key)
|
|
||||||
with nogil:
|
|
||||||
self.p.putFloat(k, val)
|
|
||||||
|
|
||||||
def put_nonblocking(self, key, dat):
|
|
||||||
cdef string k = self.check_key(key)
|
|
||||||
cdef string dat_bytes = self._put_cast(key, dat)
|
|
||||||
with nogil:
|
|
||||||
self.p.putNonBlocking(k, dat_bytes)
|
|
||||||
|
|
||||||
def put_bool_nonblocking(self, key, bool val):
|
|
||||||
cdef string k = self.check_key(key)
|
|
||||||
with nogil:
|
|
||||||
self.p.putBoolNonBlocking(k, val)
|
|
||||||
|
|
||||||
def put_int_nonblocking(self, key, int val):
|
|
||||||
cdef string k = self.check_key(key)
|
|
||||||
with nogil:
|
|
||||||
self.p.putIntNonBlocking(k, val)
|
|
||||||
|
|
||||||
def put_float_nonblocking(self, key, float val):
|
|
||||||
cdef string k = self.check_key(key)
|
|
||||||
with nogil:
|
|
||||||
self.p.putFloatNonBlocking(k, val)
|
|
||||||
|
|
||||||
def remove(self, key):
|
def remove(self, key):
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
@@ -221,8 +177,8 @@ cdef class Params:
|
|||||||
def get_type(self, key):
|
def get_type(self, key):
|
||||||
return self.p.getKeyType(self.check_key(key))
|
return self.p.getKeyType(self.check_key(key))
|
||||||
|
|
||||||
def all_keys(self):
|
def all_keys(self, flag=ParamKeyFlag.ALL):
|
||||||
return self.p.allKeys()
|
return self.p.allKeys(flag)
|
||||||
|
|
||||||
def get_default_value(self, key):
|
def get_default_value(self, key):
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
|
|||||||
+89
-19
@@ -2,23 +2,14 @@ import numpy as np
|
|||||||
from numbers import Number
|
from numbers import Number
|
||||||
|
|
||||||
class PIDController:
|
class PIDController:
|
||||||
def __init__(self, k_p, k_i, k_f=0., k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100):
|
def __init__(self, k_p, k_i, k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100):
|
||||||
self._k_p = k_p
|
self._k_p: list[list[float]] = [[0], [k_p]] if isinstance(k_p, Number) else k_p
|
||||||
self._k_i = k_i
|
self._k_i: list[list[float]] = [[0], [k_i]] if isinstance(k_i, Number) else k_i
|
||||||
self._k_d = k_d
|
self._k_d: list[list[float]] = [[0], [k_d]] if isinstance(k_d, Number) else k_d
|
||||||
self.k_f = k_f # feedforward gain
|
|
||||||
if isinstance(self._k_p, Number):
|
|
||||||
self._k_p = [[0], [self._k_p]]
|
|
||||||
if isinstance(self._k_i, Number):
|
|
||||||
self._k_i = [[0], [self._k_i]]
|
|
||||||
if isinstance(self._k_d, Number):
|
|
||||||
self._k_d = [[0], [self._k_d]]
|
|
||||||
|
|
||||||
self.pos_limit = pos_limit
|
self.set_limits(pos_limit, neg_limit)
|
||||||
self.neg_limit = neg_limit
|
|
||||||
|
|
||||||
self.i_unwind_rate = 0.3 / rate
|
self.i_dt = 1.0 / rate
|
||||||
self.i_rate = 1.0 / rate
|
|
||||||
self.speed = 0.0
|
self.speed = 0.0
|
||||||
|
|
||||||
self.reset()
|
self.reset()
|
||||||
@@ -35,9 +26,71 @@ class PIDController:
|
|||||||
def k_d(self):
|
def k_d(self):
|
||||||
return np.interp(self.speed, self._k_d[0], self._k_d[1])
|
return np.interp(self.speed, self._k_d[0], self._k_d[1])
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.p = 0.0
|
||||||
|
self.i = 0.0
|
||||||
|
self.d = 0.0
|
||||||
|
self.f = 0.0
|
||||||
|
self.control = 0
|
||||||
|
|
||||||
|
def set_limits(self, pos_limit, neg_limit):
|
||||||
|
self.pos_limit = pos_limit
|
||||||
|
self.neg_limit = neg_limit
|
||||||
|
|
||||||
|
def update(self, error, error_rate=0.0, speed=0.0, feedforward=0., freeze_integrator=False):
|
||||||
|
self.speed = speed
|
||||||
|
self.p = self.k_p * float(error)
|
||||||
|
self.d = self.k_d * error_rate
|
||||||
|
self.f = feedforward
|
||||||
|
|
||||||
|
if not freeze_integrator:
|
||||||
|
i = self.i + self.k_i * self.i_dt * error
|
||||||
|
|
||||||
|
# Don't allow windup if already clipping
|
||||||
|
test_control = self.p + i + self.d + self.f
|
||||||
|
i_upperbound = self.i if test_control > self.pos_limit else self.pos_limit
|
||||||
|
i_lowerbound = self.i if test_control < self.neg_limit else self.neg_limit
|
||||||
|
self.i = np.clip(i, i_lowerbound, i_upperbound)
|
||||||
|
|
||||||
|
control = self.p + self.i + self.d + self.f
|
||||||
|
self.control = np.clip(control, self.neg_limit, self.pos_limit)
|
||||||
|
return self.control
|
||||||
|
|
||||||
|
|
||||||
|
class MultiplicativeUnwindPID:
|
||||||
|
def __init__(self, k_p, k_i, k_f=0., k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100, min_cmd=1e-10, ki_red_time=1.0):
|
||||||
|
if isinstance(k_p, Number):
|
||||||
|
k_p = [[0], [k_p]]
|
||||||
|
if isinstance(k_i, Number):
|
||||||
|
k_i = [[0], [k_i]]
|
||||||
|
if isinstance(k_d, Number):
|
||||||
|
k_d = [[0], [k_d]]
|
||||||
|
self._k_p = k_p
|
||||||
|
self._k_i = k_i
|
||||||
|
self._k_d = k_d
|
||||||
|
self.k_f = float(k_f)
|
||||||
|
self.pos_limit = pos_limit
|
||||||
|
self.neg_limit = neg_limit
|
||||||
|
self.rate = float(rate)
|
||||||
|
self.i_dt = 1.0 / rate
|
||||||
|
self.min_cmd = abs(min_cmd)
|
||||||
|
self.ki_red_time = float(ki_red_time)
|
||||||
|
self.override_prev = False
|
||||||
|
self.i_unwind_factor = 1.0
|
||||||
|
self.speed = 0.0
|
||||||
|
self.reset()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def error_integral(self):
|
def k_p(self):
|
||||||
return self.i/self.k_i
|
return np.interp(self.speed, self._k_p[0], self._k_p[1])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def k_i(self):
|
||||||
|
return np.interp(self.speed, self._k_i[0], self._k_i[1])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def k_d(self):
|
||||||
|
return np.interp(self.speed, self._k_d[0], self._k_d[1])
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.p = 0.0
|
self.p = 0.0
|
||||||
@@ -46,6 +99,19 @@ class PIDController:
|
|||||||
self.f = 0.0
|
self.f = 0.0
|
||||||
self.control = 0
|
self.control = 0
|
||||||
|
|
||||||
|
def _calc_unwind_factor(self, override):
|
||||||
|
if not override or self.override_prev:
|
||||||
|
return
|
||||||
|
if self.ki_red_time <= 0.0:
|
||||||
|
self.i_unwind_factor = 1.0
|
||||||
|
return
|
||||||
|
if abs(self.i) <= self.min_cmd:
|
||||||
|
self.i_unwind_factor = 0.0
|
||||||
|
return
|
||||||
|
steps = max(int(self.ki_red_time * self.rate), 1)
|
||||||
|
factor = (self.min_cmd / abs(self.i)) ** (1.0 / steps)
|
||||||
|
self.i_unwind_factor = min(factor, 1.0)
|
||||||
|
|
||||||
def update(self, error, error_rate=0.0, speed=0.0, override=False, feedforward=0., freeze_integrator=False):
|
def update(self, error, error_rate=0.0, speed=0.0, override=False, feedforward=0., freeze_integrator=False):
|
||||||
self.speed = speed
|
self.speed = speed
|
||||||
|
|
||||||
@@ -54,10 +120,13 @@ class PIDController:
|
|||||||
self.d = error_rate * self.k_d
|
self.d = error_rate * self.k_d
|
||||||
|
|
||||||
if override:
|
if override:
|
||||||
self.i -= self.i_unwind_rate * float(np.sign(self.i))
|
self._calc_unwind_factor(override)
|
||||||
|
self.i *= self.i_unwind_factor
|
||||||
|
if abs(self.i) < self.min_cmd:
|
||||||
|
self.i = 0.0
|
||||||
else:
|
else:
|
||||||
if not freeze_integrator:
|
if not freeze_integrator:
|
||||||
self.i = self.i + error * self.k_i * self.i_rate
|
self.i = self.i + error * self.k_i * self.i_dt
|
||||||
|
|
||||||
# Clip i to prevent exceeding control limits
|
# Clip i to prevent exceeding control limits
|
||||||
control_no_i = self.p + self.d + self.f
|
control_no_i = self.p + self.d + self.f
|
||||||
@@ -67,4 +136,5 @@ class PIDController:
|
|||||||
control = self.p + self.i + self.d + self.f
|
control = self.p + self.i + self.d + self.f
|
||||||
|
|
||||||
self.control = np.clip(control, self.neg_limit, self.pos_limit)
|
self.control = np.clip(control, self.neg_limit, self.pos_limit)
|
||||||
|
self.override_prev = override
|
||||||
return self.control
|
return self.control
|
||||||
|
|||||||
+9
-5
@@ -13,7 +13,11 @@ public:
|
|||||||
if (prefix.empty()) {
|
if (prefix.empty()) {
|
||||||
prefix = util::random_string(15);
|
prefix = util::random_string(15);
|
||||||
}
|
}
|
||||||
msgq_path = Path::shm_path() + "/" + prefix;
|
#ifdef __APPLE__
|
||||||
|
msgq_path = "/tmp/msgq_" + prefix;
|
||||||
|
#else
|
||||||
|
msgq_path = "/dev/shm/msgq_" + prefix;
|
||||||
|
#endif
|
||||||
bool ret = util::create_directories(msgq_path, 0777);
|
bool ret = util::create_directories(msgq_path, 0777);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
setenv("OPENPILOT_PREFIX", prefix.c_str(), 1);
|
setenv("OPENPILOT_PREFIX", prefix.c_str(), 1);
|
||||||
@@ -23,14 +27,14 @@ public:
|
|||||||
auto param_path = Params().getParamPath();
|
auto param_path = Params().getParamPath();
|
||||||
if (util::file_exists(param_path)) {
|
if (util::file_exists(param_path)) {
|
||||||
std::string real_path = util::readlink(param_path);
|
std::string real_path = util::readlink(param_path);
|
||||||
system(util::string_format("rm %s -rf", real_path.c_str()).c_str());
|
util::check_system(util::string_format("rm %s -rf", real_path.c_str()));
|
||||||
unlink(param_path.c_str());
|
unlink(param_path.c_str());
|
||||||
}
|
}
|
||||||
if (getenv("COMMA_CACHE") == nullptr) {
|
if (getenv("COMMA_CACHE") == nullptr) {
|
||||||
system(util::string_format("rm %s -rf", Path::download_cache_root().c_str()).c_str());
|
util::check_system(util::string_format("rm %s -rf", Path::download_cache_root().c_str()));
|
||||||
}
|
}
|
||||||
system(util::string_format("rm %s -rf", Path::comma_home().c_str()).c_str());
|
util::check_system(util::string_format("rm %s -rf", Path::comma_home().c_str()));
|
||||||
system(util::string_format("rm %s -rf", msgq_path.c_str()).c_str());
|
util::check_system(util::string_format("rm %s -rf", msgq_path.c_str()));
|
||||||
unsetenv("OPENPILOT_PREFIX");
|
unsetenv("OPENPILOT_PREFIX");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-7
@@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
@@ -9,20 +10,20 @@ from openpilot.system.hardware.hw import Paths
|
|||||||
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
|
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
|
||||||
|
|
||||||
class OpenpilotPrefix:
|
class OpenpilotPrefix:
|
||||||
def __init__(self, prefix: str = None, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False):
|
def __init__(self, prefix: str | None = None, create_dirs_on_enter: bool = True, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False):
|
||||||
self.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15])
|
self.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15])
|
||||||
self.msgq_path = os.path.join(Paths.shm_path(), self.prefix)
|
shm_path = "/tmp" if platform.system() == "Darwin" else "/dev/shm"
|
||||||
|
self.msgq_path = os.path.join(shm_path, "msgq_" + self.prefix)
|
||||||
|
self.create_dirs_on_enter = create_dirs_on_enter
|
||||||
self.clean_dirs_on_exit = clean_dirs_on_exit
|
self.clean_dirs_on_exit = clean_dirs_on_exit
|
||||||
self.shared_download_cache = shared_download_cache
|
self.shared_download_cache = shared_download_cache
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.original_prefix = os.environ.get('OPENPILOT_PREFIX', None)
|
self.original_prefix = os.environ.get('OPENPILOT_PREFIX', None)
|
||||||
os.environ['OPENPILOT_PREFIX'] = self.prefix
|
os.environ['OPENPILOT_PREFIX'] = self.prefix
|
||||||
try:
|
|
||||||
os.mkdir(self.msgq_path)
|
if self.create_dirs_on_enter:
|
||||||
except FileExistsError:
|
self.create_dirs()
|
||||||
pass
|
|
||||||
os.makedirs(Paths.log_root(), exist_ok=True)
|
|
||||||
|
|
||||||
if self.shared_download_cache:
|
if self.shared_download_cache:
|
||||||
os.environ["COMMA_CACHE"] = DEFAULT_DOWNLOAD_CACHE_ROOT
|
os.environ["COMMA_CACHE"] = DEFAULT_DOWNLOAD_CACHE_ROOT
|
||||||
@@ -40,6 +41,13 @@ class OpenpilotPrefix:
|
|||||||
pass
|
pass
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def create_dirs(self):
|
||||||
|
try:
|
||||||
|
os.mkdir(self.msgq_path)
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
os.makedirs(Paths.log_root(), exist_ok=True)
|
||||||
|
|
||||||
def clean_dirs(self):
|
def clean_dirs(self):
|
||||||
symlink_path = Params().get_param_path()
|
symlink_path = Params().get_param_path()
|
||||||
if os.path.exists(symlink_path):
|
if os.path.exists(symlink_path):
|
||||||
|
|||||||
+112
@@ -0,0 +1,112 @@
|
|||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
|
class PT2Filter:
|
||||||
|
"""
|
||||||
|
Diskreter PT2-Filter mittels Tustin (bilinear transform)
|
||||||
|
Übertragungsfunktion (kontinuierlich):
|
||||||
|
H(s) = (w0^2) / (s^2 + 2*zeta*w0*s + w0^2)
|
||||||
|
Abtastzeit dt.
|
||||||
|
"""
|
||||||
|
def __init__(self, w0: float, zeta: float, dt: float):
|
||||||
|
"""
|
||||||
|
w0: Eigenkreisfrequenz [rad/s], bestimmt u.a. die Anstiegszeit
|
||||||
|
zeta: Dämpfungsgrad (zeta=1 => kritisch gedämpft)
|
||||||
|
dt: Abtastzeit [s]
|
||||||
|
"""
|
||||||
|
self.w0 = w0
|
||||||
|
self.zeta = zeta
|
||||||
|
self.dt = dt
|
||||||
|
self.a1, self.a2, self.b0, self.b1, self.b2 = self._design_pt2(self.w0, self.zeta, self.dt)
|
||||||
|
self.y1 = 0.0
|
||||||
|
self.y2 = 0.0
|
||||||
|
self.u1 = 0.0
|
||||||
|
self.u2 = 0.0
|
||||||
|
|
||||||
|
def _design_pt2(self, w0, zeta, dt):
|
||||||
|
"""
|
||||||
|
Erzeuge (a1, a2, b0, b1, b2) aus:
|
||||||
|
H(s) = w0^2 / [s^2 + 2*zeta*w0 s + w0^2]
|
||||||
|
via Tustin (s = (2/dt)*(1-z^-1)/(1+z^-1)).
|
||||||
|
|
||||||
|
Wir bringen G(z) in die Normalform:
|
||||||
|
Y(z)/U(z) = (b0 + b1 z^-1 + b2 z^-2) / (1 + a1 z^-1 + a2 z^-2).
|
||||||
|
|
||||||
|
=> Zeitbereich: y[k] = -a1*y[k-1] - a2*y[k-2] + b0*u[k] + b1*u[k-1] + b2*u[k-2].
|
||||||
|
"""
|
||||||
|
|
||||||
|
Ts = dt
|
||||||
|
wd = w0
|
||||||
|
alpha = 2.0 / Ts
|
||||||
|
b2_ = w0**2
|
||||||
|
b1_ = 2.0 * w0**2
|
||||||
|
b0_ = w0**2
|
||||||
|
A2_f1 = alpha**2
|
||||||
|
A1_f1 = -2.0 * alpha**2
|
||||||
|
A0_f1 = alpha**2
|
||||||
|
factor2 = 2.0*zeta*wd*alpha
|
||||||
|
A2_f2 = factor2
|
||||||
|
A1_f2 = 0.0
|
||||||
|
A0_f2 = -factor2
|
||||||
|
A2_f3 = wd**2
|
||||||
|
A1_f3 = 2.0*(wd**2)
|
||||||
|
A0_f3 = wd**2
|
||||||
|
A2 = A2_f1 + A2_f2 + A2_f3
|
||||||
|
A1 = A1_f1 + A1_f2 + A1_f3
|
||||||
|
A0 = A0_f1 + A0_f2 + A0_f3
|
||||||
|
B2 = b2_
|
||||||
|
B1 = b1_
|
||||||
|
B0 = b0_
|
||||||
|
b2d = B2 / A2
|
||||||
|
b1d = B1 / A2
|
||||||
|
b0d = B0 / A2
|
||||||
|
a2d = A0 / A2
|
||||||
|
a1d = A1 / A2
|
||||||
|
|
||||||
|
return (a1d, a2d, b0d, b1d, b2d)
|
||||||
|
|
||||||
|
def sync(self, target: float):
|
||||||
|
steps = compute_saturation_steps(self.w0, self.zeta, self.dt)
|
||||||
|
for i in range(1, steps + 1):
|
||||||
|
update(target)
|
||||||
|
|
||||||
|
def compute_saturation_steps(self, w0: float, zeta: float, dt: float) -> int:
|
||||||
|
"""
|
||||||
|
Berechnet eine Abschätzung der Schritte, bis der Filter (95% des Endwerts) erreicht ist.
|
||||||
|
|
||||||
|
Wir nutzen hier die Abschätzung:
|
||||||
|
T_s = 4 / (zeta * w0)
|
||||||
|
und setzen N = T_s / dt.
|
||||||
|
"""
|
||||||
|
Ts = 4.0 / (zeta * w0)
|
||||||
|
N = Ts / dt
|
||||||
|
return math.ceil(N)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""
|
||||||
|
Setzt interne Zustände zurück
|
||||||
|
"""
|
||||||
|
self.y1 = 0.0
|
||||||
|
self.y2 = 0.0
|
||||||
|
self.u1 = 0.0
|
||||||
|
self.u2 = 0.0
|
||||||
|
|
||||||
|
def update(self, u: float) -> float:
|
||||||
|
"""
|
||||||
|
Ein Schritt des Filters mit aktuellem Eingang u.
|
||||||
|
Gibt Ausgang y zurück.
|
||||||
|
"""
|
||||||
|
y = (
|
||||||
|
- self.a1 * self.y1
|
||||||
|
- self.a2 * self.y2
|
||||||
|
+ self.b0 * u
|
||||||
|
+ self.b1 * self.u1
|
||||||
|
+ self.b2 * self.u2
|
||||||
|
)
|
||||||
|
|
||||||
|
self.y2 = self.y1
|
||||||
|
self.y1 = y
|
||||||
|
self.u2 = self.u1
|
||||||
|
self.u1 = u
|
||||||
|
|
||||||
|
return y
|
||||||
@@ -6,9 +6,9 @@
|
|||||||
#include "common/timing.h"
|
#include "common/timing.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
||||||
RateKeeper::RateKeeper(const std::string &name, float rate, float print_delay_threshold)
|
RateKeeper::RateKeeper(const std::string &name_, float rate, float print_delay_threshold_)
|
||||||
: name(name),
|
: name(name_),
|
||||||
print_delay_threshold(std::max(0.f, print_delay_threshold)) {
|
print_delay_threshold(std::max(0.f, print_delay_threshold_)) {
|
||||||
interval = 1 / rate;
|
interval = 1 / rate;
|
||||||
last_monitor_time = seconds_since_boot();
|
last_monitor_time = seconds_since_boot();
|
||||||
next_frame_time = last_monitor_time + interval;
|
next_frame_time = last_monitor_time + interval;
|
||||||
|
|||||||
+6
-1
@@ -6,7 +6,7 @@ import time
|
|||||||
|
|
||||||
from setproctitle import getproctitle
|
from setproctitle import getproctitle
|
||||||
|
|
||||||
from openpilot.common.util import MovingAverage
|
from openpilot.common.utils import MovingAverage
|
||||||
from openpilot.system.hardware import PC
|
from openpilot.system.hardware import PC
|
||||||
|
|
||||||
|
|
||||||
@@ -28,6 +28,11 @@ class Priority:
|
|||||||
CTRL_HIGH = 53
|
CTRL_HIGH = 53
|
||||||
|
|
||||||
|
|
||||||
|
def drop_realtime() -> None:
|
||||||
|
if sys.platform == 'linux' and not PC:
|
||||||
|
os.sched_setscheduler(0, os.SCHED_OTHER, os.sched_param(0))
|
||||||
|
|
||||||
|
|
||||||
def set_core_affinity(cores: list[int]) -> None:
|
def set_core_affinity(cores: list[int]) -> None:
|
||||||
if sys.platform == 'linux' and not PC:
|
if sys.platform == 'linux' and not PC:
|
||||||
os.sched_setaffinity(0, cores)
|
os.sched_setaffinity(0, cores)
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
import time
|
|
||||||
import functools
|
|
||||||
|
|
||||||
from openpilot.common.swaglog import cloudlog
|
|
||||||
|
|
||||||
|
|
||||||
def retry(attempts=3, delay=1.0, ignore_failure=False):
|
|
||||||
def decorator(func):
|
|
||||||
@functools.wraps(func)
|
|
||||||
def wrapper(*args, **kwargs):
|
|
||||||
for _ in range(attempts):
|
|
||||||
try:
|
|
||||||
return func(*args, **kwargs)
|
|
||||||
except Exception:
|
|
||||||
cloudlog.exception(f"{func.__name__} failed, trying again")
|
|
||||||
time.sleep(delay)
|
|
||||||
|
|
||||||
if ignore_failure:
|
|
||||||
cloudlog.error(f"{func.__name__} failed after retry")
|
|
||||||
else:
|
|
||||||
raise Exception(f"{func.__name__} failed after retry")
|
|
||||||
return wrapper
|
|
||||||
return decorator
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
@retry(attempts=10)
|
|
||||||
def abc():
|
|
||||||
raise ValueError("abc failed :(")
|
|
||||||
abc()
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import subprocess
|
|
||||||
|
|
||||||
|
|
||||||
def run_cmd(cmd: list[str], cwd=None, env=None) -> str:
|
|
||||||
return subprocess.check_output(cmd, encoding='utf8', cwd=cwd, env=env).strip()
|
|
||||||
|
|
||||||
|
|
||||||
def run_cmd_default(cmd: list[str], default: str = "", cwd=None, env=None) -> str:
|
|
||||||
try:
|
|
||||||
return run_cmd(cmd, cwd=cwd, env=env)
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
return default
|
|
||||||
|
|
||||||
Regular → Executable
+2
-2
@@ -6,9 +6,9 @@ from openpilot.common.basedir import BASEDIR
|
|||||||
class Spinner:
|
class Spinner:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
try:
|
try:
|
||||||
self.spinner_proc = subprocess.Popen(["./spinner"],
|
self.spinner_proc = subprocess.Popen(["./spinner.py"],
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
cwd=os.path.join(BASEDIR, "selfdrive", "ui"),
|
cwd=os.path.join(BASEDIR, "system", "ui"),
|
||||||
close_fds=True)
|
close_fds=True)
|
||||||
except OSError:
|
except OSError:
|
||||||
self.spinner_proc = None
|
self.spinner_proc = None
|
||||||
|
|||||||
+4
-2
@@ -11,10 +11,12 @@
|
|||||||
|
|
||||||
#include <zmq.h>
|
#include <zmq.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "third_party/json11/json11.hpp"
|
#include "json11/json11.hpp"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
#include "system/hardware/hw.h"
|
#include "system/hardware/hw.h"
|
||||||
|
|
||||||
|
#include "sunnypilot/common/version.h"
|
||||||
|
|
||||||
class SwaglogState {
|
class SwaglogState {
|
||||||
public:
|
public:
|
||||||
SwaglogState() {
|
SwaglogState() {
|
||||||
@@ -56,7 +58,7 @@ public:
|
|||||||
if (char* daemon_name = getenv("MANAGER_DAEMON")) {
|
if (char* daemon_name = getenv("MANAGER_DAEMON")) {
|
||||||
ctx_j["daemon"] = daemon_name;
|
ctx_j["daemon"] = daemon_name;
|
||||||
}
|
}
|
||||||
ctx_j["version"] = COMMA_VERSION;
|
ctx_j["version"] = SUNNYPILOT_VERSION;
|
||||||
ctx_j["dirty"] = !getenv("CLEAN");
|
ctx_j["dirty"] = !getenv("CLEAN");
|
||||||
ctx_j["device"] = Hardware::get_name();
|
ctx_j["device"] = Hardware::get_name();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from openpilot.common.file_helpers import atomic_write_in_dir
|
from openpilot.common.utils import atomic_write
|
||||||
|
|
||||||
|
|
||||||
class TestFileHelpers:
|
class TestFileHelpers:
|
||||||
@@ -15,5 +15,5 @@ class TestFileHelpers:
|
|||||||
assert f.read() == "test"
|
assert f.read() == "test"
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
|
|
||||||
def test_atomic_write_in_dir(self):
|
def test_atomic_write(self):
|
||||||
self.run_atomic_write_func(atomic_write_in_dir)
|
self.run_atomic_write_func(atomic_write)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from openpilot.common.markdown import parse_markdown
|
|||||||
|
|
||||||
class TestMarkdown:
|
class TestMarkdown:
|
||||||
def test_all_release_notes(self):
|
def test_all_release_notes(self):
|
||||||
with open(os.path.join(BASEDIR, "RELEASES.md")) as f:
|
with open(os.path.join(BASEDIR, "CHANGELOG.md")) as f:
|
||||||
release_notes = f.read().split("\n\n")
|
release_notes = f.read().split("\n\n")
|
||||||
assert len(release_notes) > 10
|
assert len(release_notes) > 10
|
||||||
|
|
||||||
|
|||||||
+53
-21
@@ -1,27 +1,28 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
import datetime
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from openpilot.common.params import Params, ParamKeyType, UnknownKeyName
|
from openpilot.common.params import Params, ParamKeyFlag, UnknownKeyName
|
||||||
|
|
||||||
class TestParams:
|
class TestParams:
|
||||||
def setup_method(self):
|
def setup_method(self):
|
||||||
self.params = Params()
|
self.params = Params()
|
||||||
|
|
||||||
def test_params_put_and_get(self):
|
def test_params_put_and_get(self):
|
||||||
self.params.put("DongleId", "cb38263377b873ee")
|
self.params.put("DongleId", "cb38263377b873ee", block=True)
|
||||||
assert self.params.get("DongleId") == b"cb38263377b873ee"
|
assert self.params.get("DongleId") == "cb38263377b873ee"
|
||||||
|
|
||||||
def test_params_non_ascii(self):
|
def test_params_non_ascii(self):
|
||||||
st = b"\xe1\x90\xff"
|
st = b"\xe1\x90\xff"
|
||||||
self.params.put("CarParams", st)
|
self.params.put("CarParams", st, block=True)
|
||||||
assert self.params.get("CarParams") == st
|
assert self.params.get("CarParams") == st
|
||||||
|
|
||||||
def test_params_get_cleared_manager_start(self):
|
def test_params_get_cleared_manager_start(self):
|
||||||
self.params.put("CarParams", "test")
|
self.params.put("CarParams", b"test", block=True)
|
||||||
self.params.put("DongleId", "cb38263377b873ee")
|
self.params.put("DongleId", "cb38263377b873ee", block=True)
|
||||||
assert self.params.get("CarParams") == b"test"
|
assert self.params.get("CarParams") == b"test"
|
||||||
|
|
||||||
undefined_param = self.params.get_param_path(uuid.uuid4().hex)
|
undefined_param = self.params.get_param_path(uuid.uuid4().hex)
|
||||||
@@ -29,24 +30,24 @@ class TestParams:
|
|||||||
f.write("test")
|
f.write("test")
|
||||||
assert os.path.isfile(undefined_param)
|
assert os.path.isfile(undefined_param)
|
||||||
|
|
||||||
self.params.clear_all(ParamKeyType.CLEAR_ON_MANAGER_START)
|
self.params.clear_all(ParamKeyFlag.CLEAR_ON_MANAGER_START)
|
||||||
assert self.params.get("CarParams") is None
|
assert self.params.get("CarParams") is None
|
||||||
assert self.params.get("DongleId") is not None
|
assert self.params.get("DongleId") is not None
|
||||||
assert not os.path.isfile(undefined_param)
|
assert not os.path.isfile(undefined_param)
|
||||||
|
|
||||||
def test_params_two_things(self):
|
def test_params_two_things(self):
|
||||||
self.params.put("DongleId", "bob")
|
self.params.put("DongleId", "bob", block=True)
|
||||||
self.params.put("AthenadPid", "123")
|
self.params.put("AthenadPid", 123, block=True)
|
||||||
assert self.params.get("DongleId") == b"bob"
|
assert self.params.get("DongleId") == "bob"
|
||||||
assert self.params.get("AthenadPid") == b"123"
|
assert self.params.get("AthenadPid") == 123
|
||||||
|
|
||||||
def test_params_get_block(self):
|
def test_params_get_block(self):
|
||||||
def _delayed_writer():
|
def _delayed_writer():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
self.params.put("CarParams", "test")
|
self.params.put("CarParams", b"test", block=True)
|
||||||
threading.Thread(target=_delayed_writer).start()
|
threading.Thread(target=_delayed_writer).start()
|
||||||
assert self.params.get("CarParams") is None
|
assert self.params.get("CarParams") is None
|
||||||
assert self.params.get("CarParams", True) == b"test"
|
assert self.params.get("CarParams", block=True) == b"test"
|
||||||
|
|
||||||
def test_params_unknown_key_fails(self):
|
def test_params_unknown_key_fails(self):
|
||||||
with pytest.raises(UnknownKeyName):
|
with pytest.raises(UnknownKeyName):
|
||||||
@@ -56,10 +57,10 @@ class TestParams:
|
|||||||
self.params.get_bool("swag")
|
self.params.get_bool("swag")
|
||||||
|
|
||||||
with pytest.raises(UnknownKeyName):
|
with pytest.raises(UnknownKeyName):
|
||||||
self.params.put("swag", "abc")
|
self.params.put("swag", "abc", block=True)
|
||||||
|
|
||||||
with pytest.raises(UnknownKeyName):
|
with pytest.raises(UnknownKeyName):
|
||||||
self.params.put_bool("swag", True)
|
self.params.put_bool("swag", True, block=True)
|
||||||
|
|
||||||
def test_remove_not_there(self):
|
def test_remove_not_there(self):
|
||||||
assert self.params.get("CarParams") is None
|
assert self.params.get("CarParams") is None
|
||||||
@@ -70,23 +71,23 @@ class TestParams:
|
|||||||
self.params.remove("IsMetric")
|
self.params.remove("IsMetric")
|
||||||
assert not self.params.get_bool("IsMetric")
|
assert not self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put_bool("IsMetric", True)
|
self.params.put_bool("IsMetric", True, block=True)
|
||||||
assert self.params.get_bool("IsMetric")
|
assert self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put_bool("IsMetric", False)
|
self.params.put_bool("IsMetric", False, block=True)
|
||||||
assert not self.params.get_bool("IsMetric")
|
assert not self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put("IsMetric", "1")
|
self.params.put("IsMetric", True, block=True)
|
||||||
assert self.params.get_bool("IsMetric")
|
assert self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put("IsMetric", "0")
|
self.params.put("IsMetric", False, block=True)
|
||||||
assert not self.params.get_bool("IsMetric")
|
assert not self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
def test_put_non_blocking_with_get_block(self):
|
def test_put_non_blocking_with_get_block(self):
|
||||||
q = Params()
|
q = Params()
|
||||||
def _delayed_writer():
|
def _delayed_writer():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
Params().put_nonblocking("CarParams", "test")
|
Params().put("CarParams", b"test")
|
||||||
threading.Thread(target=_delayed_writer).start()
|
threading.Thread(target=_delayed_writer).start()
|
||||||
assert q.get("CarParams") is None
|
assert q.get("CarParams") is None
|
||||||
assert q.get("CarParams", True) == b"test"
|
assert q.get("CarParams", True) == b"test"
|
||||||
@@ -95,7 +96,7 @@ class TestParams:
|
|||||||
q = Params()
|
q = Params()
|
||||||
def _delayed_writer():
|
def _delayed_writer():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
Params().put_bool_nonblocking("CarParams", True)
|
Params().put_bool("CarParams", True)
|
||||||
threading.Thread(target=_delayed_writer).start()
|
threading.Thread(target=_delayed_writer).start()
|
||||||
assert q.get("CarParams") is None
|
assert q.get("CarParams") is None
|
||||||
assert q.get("CarParams", True) == b"1"
|
assert q.get("CarParams", True) == b"1"
|
||||||
@@ -107,3 +108,34 @@ class TestParams:
|
|||||||
assert len(keys) > 20
|
assert len(keys) > 20
|
||||||
assert len(keys) == len(set(keys))
|
assert len(keys) == len(set(keys))
|
||||||
assert b"CarParams" in keys
|
assert b"CarParams" in keys
|
||||||
|
|
||||||
|
def test_params_default_value(self):
|
||||||
|
self.params.remove("LanguageSetting")
|
||||||
|
self.params.remove("LongitudinalPersonality")
|
||||||
|
self.params.remove("LiveParameters")
|
||||||
|
|
||||||
|
assert self.params.get("LanguageSetting") is None
|
||||||
|
assert self.params.get("LanguageSetting", return_default=False) is None
|
||||||
|
assert isinstance(self.params.get("LanguageSetting", return_default=True), str)
|
||||||
|
assert isinstance(self.params.get("LongitudinalPersonality", return_default=True), int)
|
||||||
|
assert self.params.get("LiveParameters") is None
|
||||||
|
assert self.params.get("LiveParameters", return_default=True) is None
|
||||||
|
|
||||||
|
def test_params_get_type(self):
|
||||||
|
# json
|
||||||
|
self.params.put("ApiCache_FirehoseStats", {"a": 0}, block=True)
|
||||||
|
assert self.params.get("ApiCache_FirehoseStats") == {"a": 0}
|
||||||
|
|
||||||
|
# int
|
||||||
|
self.params.put("BootCount", 1441, block=True)
|
||||||
|
assert self.params.get("BootCount") == 1441
|
||||||
|
|
||||||
|
# bool
|
||||||
|
self.params.put("AdbEnabled", True, block=True)
|
||||||
|
assert self.params.get("AdbEnabled")
|
||||||
|
assert isinstance(self.params.get("AdbEnabled"), bool)
|
||||||
|
|
||||||
|
# time
|
||||||
|
now = datetime.datetime.now(datetime.UTC)
|
||||||
|
self.params.put("InstallDate", now, block=True)
|
||||||
|
assert self.params.get("InstallDate") == now
|
||||||
|
|||||||
@@ -24,6 +24,6 @@ class TestSimpleKalman:
|
|||||||
self.kf.set_x([[1.0], [1.0]])
|
self.kf.set_x([[1.0], [1.0]])
|
||||||
assert self.kf.x == [[1.0], [1.0]]
|
assert self.kf.x == [[1.0], [1.0]]
|
||||||
|
|
||||||
def update_returns_state(self):
|
def test_update_returns_state(self):
|
||||||
x = self.kf.update(100)
|
x = self.kf.update(100)
|
||||||
assert x == self.kf.x
|
assert x == [i[0] for i in self.kf.x]
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
#include "system/hardware/hw.h"
|
#include "system/hardware/hw.h"
|
||||||
#include "third_party/json11/json11.hpp"
|
#include "json11/json11.hpp"
|
||||||
|
|
||||||
|
#include "sunnypilot/common/version.h"
|
||||||
|
|
||||||
std::string daemon_name = "testy";
|
std::string daemon_name = "testy";
|
||||||
std::string dongle_id = "test_dongle_id";
|
std::string dongle_id = "test_dongle_id";
|
||||||
@@ -53,7 +55,7 @@ void recv_log(int thread_cnt, int thread_msg_cnt) {
|
|||||||
REQUIRE(ctx["dongle_id"].string_value() == dongle_id);
|
REQUIRE(ctx["dongle_id"].string_value() == dongle_id);
|
||||||
REQUIRE(ctx["dirty"].bool_value() == true);
|
REQUIRE(ctx["dirty"].bool_value() == true);
|
||||||
|
|
||||||
REQUIRE(ctx["version"].string_value() == COMMA_VERSION);
|
REQUIRE(ctx["version"].string_value() == SUNNYPILOT_VERSION);
|
||||||
|
|
||||||
std::string device = Hardware::get_name();
|
std::string device = Hardware::get_name();
|
||||||
REQUIRE(ctx["device"].string_value() == device);
|
REQUIRE(ctx["device"].string_value() == device);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ TEST_CASE("util::read_file") {
|
|||||||
REQUIRE(util::read_file(filename).empty());
|
REQUIRE(util::read_file(filename).empty());
|
||||||
|
|
||||||
std::string content = random_bytes(64 * 1024);
|
std::string content = random_bytes(64 * 1024);
|
||||||
write(fd, content.c_str(), content.size());
|
REQUIRE(write(fd, content.c_str(), content.size()) == (ssize_t)content.size());
|
||||||
std::string ret = util::read_file(filename);
|
std::string ret = util::read_file(filename);
|
||||||
bool equal = (ret == content);
|
bool equal = (ret == content);
|
||||||
REQUIRE(equal);
|
REQUIRE(equal);
|
||||||
@@ -114,12 +114,12 @@ TEST_CASE("util::safe_fwrite") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("util::create_directories") {
|
TEST_CASE("util::create_directories") {
|
||||||
system("rm /tmp/test_create_directories -rf");
|
REQUIRE(system("rm /tmp/test_create_directories -rf") == 0);
|
||||||
std::string dir = "/tmp/test_create_directories/a/b/c/d/e/f";
|
std::string dir = "/tmp/test_create_directories/a/b/c/d/e/f";
|
||||||
|
|
||||||
auto check_dir_permissions = [](const std::string &dir, mode_t mode) -> bool {
|
auto check_dir_permissions = [](const std::string &path, mode_t mode) -> bool {
|
||||||
struct stat st = {};
|
struct stat st = {};
|
||||||
return stat(dir.c_str(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR && (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) == mode;
|
return stat(path.c_str(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR && (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) == mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
SECTION("create_directories") {
|
SECTION("create_directories") {
|
||||||
@@ -132,7 +132,7 @@ TEST_CASE("util::create_directories") {
|
|||||||
}
|
}
|
||||||
SECTION("a file exists with the same name") {
|
SECTION("a file exists with the same name") {
|
||||||
REQUIRE(util::create_directories(dir, 0755));
|
REQUIRE(util::create_directories(dir, 0755));
|
||||||
int f = open((dir + "/file").c_str(), O_RDWR | O_CREAT);
|
int f = open((dir + "/file").c_str(), O_RDWR | O_CREAT, 0644);
|
||||||
REQUIRE(f != -1);
|
REQUIRE(f != -1);
|
||||||
close(f);
|
close(f);
|
||||||
REQUIRE(util::create_directories(dir + "/file", 0755) == false);
|
REQUIRE(util::create_directories(dir + "/file", 0755) == false);
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ from openpilot.common.basedir import BASEDIR
|
|||||||
class TextWindow:
|
class TextWindow:
|
||||||
def __init__(self, text):
|
def __init__(self, text):
|
||||||
try:
|
try:
|
||||||
self.text_proc = subprocess.Popen(["./text", text],
|
self.text_proc = subprocess.Popen(["./text.py", text],
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
cwd=os.path.join(BASEDIR, "selfdrive", "ui"),
|
cwd=os.path.join(BASEDIR, "system", "ui"),
|
||||||
close_fds=True)
|
close_fds=True)
|
||||||
except OSError:
|
except OSError:
|
||||||
self.text_proc = None
|
self.text_proc = None
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import datetime
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
MIN_DATE = datetime.datetime(year=2025, month=2, day=21)
|
MIN_DATE = datetime.datetime(year=2025, month=2, day=21)
|
||||||
|
MAX_DATE = datetime.datetime(year=2035, month=1, day=1)
|
||||||
|
|
||||||
def min_date():
|
def min_date():
|
||||||
# on systemd systems, the default time is the systemd build time
|
# on systemd systems, the default time is the systemd build time
|
||||||
@@ -12,4 +13,4 @@ def min_date():
|
|||||||
return MIN_DATE
|
return MIN_DATE
|
||||||
|
|
||||||
def system_time_valid():
|
def system_time_valid():
|
||||||
return datetime.datetime.now() > min_date()
|
return min_date() < datetime.datetime.now() < MAX_DATE
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user