2 Commits

Author SHA1 Message Date
1okko 5c0feefabd 666 2026-05-10 07:59:33 +08:00
github-actions[bot] 54e6124925 sunnypilot v2026.05.07-4485
version: sunnypilot v2026.001.000 (dev)
date: 2026-05-07T23:07:19
master commit: c28eb958740187620f2282023b8f1997cf90f583
2026-05-07 23:07:19 +00:00
4230 changed files with 541588 additions and 538405 deletions
+6
View File
@@ -0,0 +1,6 @@
Wen
REGIST
PullRequest
cancelled
FOF
NoO
-47
View File
@@ -1,47 +0,0 @@
name: Bug report
description: For issues with running openpilot on your comma device
labels: ["bug"]
body:
- type: markdown
attributes:
value: >
Before creating a **bug report**, please check the following:
* If the issue likely only affects your car model or make, go back and open a **car bug report** instead.
* If the issue is related to the driving or driver monitoring models, you should open a [discussion](https://github.com/commaai/openpilot/discussions/categories/model-feedback) instead.
* Ensure you're running the latest openpilot release.
* Ensure you're using officially supported hardware. Issues running on PCs have a different issue template.
* Ensure there isn't an existing issue for your bug. If there is, leave a comment on the existing issue.
* Ensure you're running stock openpilot. We cannot look into bug reports from forks.
If you're unsure whether you've hit a bug, check out the #installation-help channel in the [community Discord server](https://discord.comma.ai).
- type: textarea
attributes:
label: Describe the bug
description: Also include a description of how to reproduce the bug
validations:
required: true
- type: input
id: route
attributes:
label: Provide a route where the issue occurs
description: Ensure the route is fully uploaded at https://useradmin.comma.ai. We cannot look into issues without routes, or at least a Dongle ID.
placeholder: 77611a1fac303767|2020-05-11--16-37-07
validations:
required: true
- type: input
id: version
attributes:
label: openpilot version
description: If you're not on release, provide the commit hash
placeholder: 0.8.10
validations:
required: true
- type: textarea
attributes:
label: Additional info
-14
View File
@@ -1,14 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Car bug report
url: https://github.com/commaai/opendbc/issues/new
about: For issues with a particular car make or model
- name: Join the Discord
url: https://discord.comma.ai
about: The community Discord is for both openpilot development and experience discussion
- name: Report driving behavior feedback
url: https://discord.com/channels/469524606043160576/1254834193066623017
about: Feedback for the driving and driver monitoring models goes in the #driving-feedback in Discord
- name: Community Wiki
url: https://github.com/commaai/openpilot/wiki
about: Check out our community wiki
-8
View File
@@ -1,8 +0,0 @@
---
name: Enhancement
about: For openpilot enhancement suggestions
title: ''
labels: 'enhancement'
assignees: ''
---
-42
View File
@@ -1,42 +0,0 @@
name: PC bug report
description: For issues with running openpilot on PC
labels: ["PC"]
body:
- type: markdown
attributes:
value: >
Before creating a **bug report**, please check the following:
* Ensure you're running the latest openpilot release.
* Ensure there isn't an existing issue for your bug. If there is, leave a comment on the existing issue.
* Ensure you're running stock openpilot. We cannot look into bug reports from forks.
If you're unsure whether you've hit a bug, check out the #installation-help channel in the [community Discord server](https://discord.comma.ai).
- type: textarea
attributes:
label: Describe the bug
description: Also include a description of how to reproduce the bug
validations:
required: true
- type: input
id: os-version
attributes:
label: OS Version
placeholder: Ubuntu 24.04
validations:
required: true
- type: input
id: version
attributes:
label: openpilot version or commit
placeholder: bd36f2ec8d3559909678eff2690c10a520938367
validations:
required: false
- type: textarea
attributes:
label: Additional info
-27
View File
@@ -1,27 +0,0 @@
CI / testing:
- changed-files:
- any-glob-to-all-files: "{.github/**,**/test_*,**/test/**,Jenkinsfile}"
car:
- changed-files:
- any-glob-to-all-files: '{selfdrive/car/**,opendbc_repo}'
simulation:
- changed-files:
- any-glob-to-all-files: 'tools/sim/**'
ui:
- changed-files:
- any-glob-to-all-files: '{selfdrive/assets/**,selfdrive/ui/**,system/ui/**}'
tools:
- changed-files:
- any-glob-to-all-files: 'tools/**'
multilanguage:
- changed-files:
- any-glob-to-all-files: 'selfdrive/ui/translations/**'
autonomy:
- changed-files:
- any-glob-to-all-files: "{selfdrive/modeld/models/**,selfdrive/test/process_replay/model_replay_ref_commit}"
-68
View File
@@ -1,68 +0,0 @@
<!-- Please copy and paste the relevant template -->
<!--- ***** Template: Fingerprint *****
**Car**
Which car (make, model, year) this fingerprint is for
**Route**
A route with the fingerprint
-->
<!--- ***** Template: Car Bugfix *****
**Description**
A description of the bug and the fix. Also link the issue if it exists.
**Verification**
Explain how you tested this bug fix.
**Route**
Route: [a route with the bug fix]
-->
<!--- ***** Template: Bugfix *****
**Description**
A description of the bug and the fix. Also link the issue if it exists.
**Verification**
Explain how you tested this bug fix.
-->
<!--- ***** Template: Car Port *****
**Checklist**
- [ ] added entry to CAR in selfdrive/car/*/values.py and ran `selfdrive/car/docs.py` to generate new docs
- [ ] test route added to [routes.py](https://github.com/commaai/openpilot/blob/master/selfdrive/car/tests/routes.py)
- [ ] route with openpilot:
- [ ] route with stock system:
- [ ] car harness used (if comma doesn't sell it, put N/A):
-->
<!--- ***** Template: Refactor *****
**Description**
A description of the refactor, including the goals it accomplishes.
**Verification**
Explain how you tested the refactor for regressions.
-->
-58
View File
@@ -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: 'true'
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 }}
-52
View File
@@ -1,52 +0,0 @@
name: "PR review"
on:
pull_request_target:
types: [opened, reopened, synchronize, 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
-37
View File
@@ -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 }} "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
-101
View File
@@ -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() && github.repository == 'commaai/openpilot'
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
-17
View File
@@ -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:
tests:
uses: commaai/openpilot/.github/workflows/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 }}
-239
View File
@@ -1,239 +0,0 @@
name: Compile StarPilot
on:
workflow_dispatch:
inputs:
not_vetted:
description: "This branch is not vetted"
type: boolean
default: false
required: false
publish_custom_branch:
description: "Push to custom branch:"
type: string
default: ""
required: false
publish_starpilot:
description: "Push to StarPilot"
type: boolean
default: false
required: false
publish_staging:
description: "Push to StarPilot-Staging"
type: boolean
default: false
required: false
publish_testing:
description: "Push to StarPilot-Testing"
type: boolean
default: false
required: false
runner:
description: "Select runner"
type: choice
options:
- c3
- c3x
default: "c3"
required: true
update_translations:
description: "Update missing/outdated translations"
type: boolean
default: false
required: false
vet_existing_translations:
description: "Vet existing translations"
type: boolean
default: false
required: false
env:
BASE_DIR: ${{ github.workspace }}
BUILD_DIR: "/data/openpilot"
CUSTOM_BRANCH: ${{ inputs.publish_custom_branch }}
GIT_EMAIL: "91348155+FrogAi@users.noreply.github.com"
GIT_NAME: "James"
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
jobs:
get_branch:
runs-on: [self-hosted, "${{ inputs.runner }}"]
outputs:
branch: ${{ steps.get_branch.outputs.branch }}
python_version: ${{ steps.get_python_version.outputs.python_version }}
steps:
- name: Get Current Branch
id: get_branch
run: |
cd "$BUILD_DIR"
echo "branch=$(git rev-parse --abbrev-ref HEAD)" >> "$GITHUB_OUTPUT"
- name: Get Python Version
id: get_python_version
run: |
echo "python_version=$(tr -d '[:space:]' < "$BUILD_DIR/.python-version")" >> $GITHUB_OUTPUT
translate:
needs: get_branch
if: inputs.update_translations
runs-on: ubuntu-latest
steps:
- name: Configure Git Identity
run: |
git config --global user.name "$GIT_NAME"
git config --global user.email "$GIT_EMAIL"
- name: Checkout Required Files
uses: actions/checkout@v4
with:
ref: ${{ needs.get_branch.outputs.branch }}
sparse-checkout: |
starpilot/ui/
selfdrive/controls/lib/alerts_offroad.json
selfdrive/ui/
selfdrive/ui/translations/
selfdrive/ui/translations/auto_translate.py
selfdrive/ui/update_translations.py
- name: Set Up Python
uses: actions/setup-python@v4
with:
cache: "pip"
python-version: ${{ needs.get_branch.outputs.python_version }}
- name: Install Dependencies
run: |
pip install requests
sudo apt-get update && sudo apt-get install -y --no-install-recommends qttools5-dev-tools
- name: Update Translations
run: |
python selfdrive/ui/update_translations.py --vanish
- name: Update Missing Translations
continue-on-error: true
timeout-minutes: 300
run: |
python selfdrive/ui/translations/auto_translate.py --all-files
- name: Vet Existing Translations
if: inputs.vet_existing_translations
continue-on-error: true
timeout-minutes: 300
run: |
python selfdrive/ui/translations/auto_translate.py --all-files --vet-translations
- name: Commit and Push Translations
run: |
if git diff --quiet selfdrive/ui/translations/*.ts; then
echo "No translation updates detected."
exit 0
fi
git fetch --unshallow origin "${{ needs.get_branch.outputs.branch }}"
git checkout "${{ needs.get_branch.outputs.branch }}"
git add selfdrive/ui/translations/*.ts
git commit --amend --no-edit
git push --force origin "${{ needs.get_branch.outputs.branch }}"
build_and_push:
needs: [get_branch, translate]
if: ${{ !failure() && !cancelled() && needs.get_branch.result == 'success' }}
runs-on: [self-hosted, "${{ inputs.runner }}"]
permissions:
contents: write
defaults:
run:
working-directory: ${{ env.BUILD_DIR }}
steps:
- name: Configure Git
run: |
git config http.postBuffer 104857600
git config user.name "$GIT_NAME"
git config user.email "$GIT_EMAIL"
git remote set-url origin "https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/FrogAi/StarPilot.git"
- name: Sync Translation Updates
if: inputs.update_translations
run: |
git fetch origin "${{ needs.get_branch.outputs.branch }}"
git reset --hard FETCH_HEAD
- name: Take Ownership of Build Directory
run: |
sudo chown -R $(whoami):$(whoami) .
- name: Clean Build Artifacts
run: |
find . -name "matlab.*.md" -delete
find . -type d \( -iname "debug" -o -iname "test" -o -iname "tests" -o -name '__pycache__' \) -exec rm -rf {} +
find . -type f \( \
-name '*.a' -o \
-name '*.o' -o \
-name '*.onnx' -o \
-name '*.os' -o \
-name '*.pyc' -o \
-name 'moc_*' \
\) -delete
find .github -mindepth 1 -maxdepth 1 ! -name 'workflows' -exec rm -rf {} +
find .github/workflows -mindepth 1 ! \( \
-type f \( \
-name 'compile_starpilot.yaml' -o \
-name 'review_pull_request.yaml' -o \
-name 'schedule_update.yaml' -o \
-name 'update_pr_branch.yaml' -o \
-name 'update_release_branch.yaml' -o \
-name 'update_tinygrad.yaml' \
\) \
\) -exec rm -rf {} +
find panda/board -type f \
! -name '__init__.py' \
! -name 'bootstub.panda.bin' \
! -name 'bootstub.panda_h7.bin' \
! -name 'panda.bin.signed' \
! -name 'panda_h7.bin.signed' \
-delete
find third_party/ -name '*Darwin*' -exec rm -rf {} +
find third_party/ -name '*x86*' -exec rm -rf {} +
rm -f .gitignore .gitmodules .gitattributes .lfsconfig .overlay_init
rm -rf .sconsign.dblite .vscode/ Jenkinsfile release/ scripts/ site_scons/ teleoprtc_repo/
find . -type d -empty ! -path "./.git*" -delete
touch prebuilt
[ "${{ inputs.not_vetted }}" = "true" ] && touch not_vetted || true
- name: Add Update Date File
if: inputs.publish_staging
continue-on-error: true
run: |
curl -fLsS https://raw.githubusercontent.com/FrogAi/StarPilot/StarPilot-Staging/.github/update_date -o .github/update_date || echo "No update_date found, skipping..."
- name: Commit and Push Build
run: |
git add -f .
git commit -m "Compile StarPilot"
git push --force origin HEAD
if [ "${{ inputs.publish_starpilot }}" = "true" ]; then
git push --force origin HEAD:StarPilot
fi
if [ "${{ inputs.publish_staging }}" = "true" ]; then
git push --force origin HEAD:StarPilot-Staging
fi
if [ "${{ inputs.publish_testing }}" = "true" ]; then
git push --force origin HEAD:StarPilot-Testing
fi
if [ -n "$CUSTOM_BRANCH" ]; then
git push --force origin HEAD:"$CUSTOM_BRANCH"
fi
-65
View File
@@ -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
-59
View File
@@ -1,59 +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 }}
permissions:
contents: write
issues: write
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 }}
- name: Delete trigger comment
if: steps.check_comment.outputs.result == 'true' && always()
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.deleteComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: context.payload.comment.id,
});
@@ -1,151 +0,0 @@
name: "mici raylib ui preview"
on:
push:
branches:
- master
pull_request_target:
types: [assigned, opened, synchronize, reopened, edited]
branches:
- 'master'
paths:
- 'selfdrive/assets/**'
- 'selfdrive/ui/**'
- 'system/ui/**'
workflow_dispatch:
env:
UI_JOB_NAME: "Create mici raylib 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 }}-mici-raylib-ui"
MASTER_BRANCH_NAME: "openpilot_master_ui_mici_raylib"
# All report files are pushed here
REPORT_FILES_BRANCH_NAME: "mici-raylib-ui-reports"
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:
- uses: actions/checkout@v4
with:
submodules: true
- 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 # filename: pr_ui/mici_ui_replay.mp4
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: mici-raylib-report-1-${{ env.REPORT_NAME }}
path: ${{ github.workspace }}/pr_ui
- name: Getting master ui # filename: master_ui_raylib/mici_ui_replay.mp4
uses: actions/checkout@v4
with:
repository: commaai/ci-artifacts
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
path: ${{ github.workspace }}/master_ui_raylib
ref: ${{ env.MASTER_BRANCH_NAME }}
- name: Saving new master ui
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
working-directory: ${{ github.workspace }}/master_ui_raylib
run: |
git checkout --orphan=new_master_ui_mici_raylib
git rm -rf *
git branch -D ${{ env.MASTER_BRANCH_NAME }}
git branch -m ${{ env.MASTER_BRANCH_NAME }}
git config user.name "GitHub Actions Bot"
git config user.email "<>"
mv ${{ github.workspace }}/pr_ui/* .
git add .
git commit -m "mici raylib video for commit ${{ env.SHA }}"
git push origin ${{ env.MASTER_BRANCH_NAME }} --force
- name: Setup FFmpeg
uses: AnimMouse/setup-ffmpeg@ae28d57dabbb148eff63170b6bf7f2b60062cbae
- name: Finding diff
if: github.event_name == 'pull_request_target'
id: find_diff
run: |
# Find the video file from PR
pr_video="${{ github.workspace }}/pr_ui/mici_ui_replay_proposed.mp4"
mv "${{ github.workspace }}/pr_ui/mici_ui_replay.mp4" "$pr_video"
master_video="${{ github.workspace }}/pr_ui/mici_ui_replay_master.mp4"
mv "${{ github.workspace }}/master_ui_raylib/mici_ui_replay.mp4" "$master_video"
# Run report
export PYTHONPATH=${{ github.workspace }}
baseurl="https://github.com/commaai/ci-artifacts/raw/refs/heads/${{ env.BRANCH_NAME }}"
diff_exit_code=0
python3 ${{ github.workspace }}/selfdrive/ui/tests/diff/diff.py "${{ github.workspace }}/pr_ui/mici_ui_replay_master.mp4" "${{ github.workspace }}/pr_ui/mici_ui_replay_proposed.mp4" "diff.html" --basedir "$baseurl" --no-open || diff_exit_code=$?
# Copy diff report files
cp ${{ github.workspace }}/selfdrive/ui/tests/diff/report/diff.html ${{ github.workspace }}/pr_ui/
cp ${{ github.workspace }}/selfdrive/ui/tests/diff/report/diff.mp4 ${{ github.workspace }}/pr_ui/
REPORT_URL="https://commaai.github.io/ci-artifacts/diff_pr_${{ github.event.number }}.html"
if [ $diff_exit_code -eq 0 ]; then
DIFF="✅ Videos are identical! [View Diff Report]($REPORT_URL)"
else
DIFF="❌ <strong>Videos differ!</strong> [View Diff Report]($REPORT_URL)"
fi
echo "DIFF=$DIFF" >> "$GITHUB_OUTPUT"
- name: Saving proposed ui
if: github.event_name == 'pull_request_target'
working-directory: ${{ github.workspace }}/master_ui_raylib
run: |
# Overwrite PR branch w/ proposed ui, and master ui at this point in time for future reference
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 "mici raylib video for PR #${{ github.event.number }}"
git push origin ${{ env.BRANCH_NAME }} --force
# Append diff report to report files branch
git fetch origin ${{ env.REPORT_FILES_BRANCH_NAME }}
git checkout ${{ env.REPORT_FILES_BRANCH_NAME }}
cp ${{ github.workspace }}/selfdrive/ui/tests/diff/report/diff.html diff_pr_${{ github.event.number }}.html
git add diff_pr_${{ github.event.number }}.html
git commit -m "mici raylib ui diff report for PR #${{ github.event.number }}" || echo "No changes to commit"
git push origin ${{ env.REPORT_FILES_BRANCH_NAME }}
- name: Comment Video on PR
if: github.event_name == 'pull_request_target'
uses: thollander/actions-comment-pull-request@v2
with:
message: |
<!-- _(run_id_video_mici_raylib **${{ github.run_id }}**)_ -->
## mici raylib UI Preview
${{ steps.find_diff.outputs.DIFF }}
comment_tag: run_id_video_mici_raylib
pr_number: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-42
View File
@@ -1,42 +0,0 @@
name: "model review"
on:
pull_request:
types: [opened, reopened, synchronize]
paths:
- 'selfdrive/modeld/models/*.onnx'
workflow_dispatch:
jobs:
comment:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
if: github.repository == 'commaai/openpilot'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Checkout master
uses: actions/checkout@v4
with:
ref: master
path: base
- run: git lfs pull
- run: cd base && git lfs pull
- run: pip install onnx
- name: scripts/reporter.py
id: report
run: |
echo "content<<EOF" >> $GITHUB_OUTPUT
echo "## Model Review" >> $GITHUB_OUTPUT
MASTER_PATH=${{ github.workspace }}/base python scripts/reporter.py >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Post model report comment
uses: marocchino/sticky-pull-request-comment@baa7203ed60924babbe5dcd0ac8eae3b66ec5e16
with:
header: model-review
message: ${{ steps.report.outputs.content }}
-39
View File
@@ -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"
-175
View File
@@ -1,175 +0,0 @@
name: "raylib ui preview"
on:
push:
branches:
- master
pull_request_target:
types: [assigned, opened, synchronize, reopened, edited]
branches:
- 'master'
paths:
- 'selfdrive/assets/**'
- 'selfdrive/ui/**'
- 'system/ui/**'
workflow_dispatch:
env:
UI_JOB_NAME: "Create raylib 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 }}-raylib-ui"
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: raylib-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_raylib
ref: openpilot_master_ui_raylib
- name: Saving new master ui
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
working-directory: ${{ github.workspace }}/master_ui_raylib
run: |
git checkout --orphan=new_master_ui_raylib
git rm -rf *
git branch -D openpilot_master_ui_raylib
git branch -m openpilot_master_ui_raylib
git config user.name "GitHub Actions Bot"
git config user.email "<>"
mv ${{ github.workspace }}/pr_ui/*.png .
git add .
git commit -m "raylib screenshots for commit ${{ env.SHA }}"
git push origin openpilot_master_ui_raylib --force
- name: Finding diff
if: github.event_name == 'pull_request_target'
id: find_diff
run: >-
sudo apt-get update && 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
# Check if the master file exists
if [ ! -f "${{ github.workspace }}/master_ui_raylib/${A[$i]}.png" ]; then
# This is a new file in PR UI that doesn't exist in master
DIFF="${DIFF}<details open>"
DIFF="${DIFF}<summary>${A[$i]} : \$\${\\color{cyan}\\text{NEW}}\$\$</summary>"
DIFF="${DIFF}<table>"
DIFF="${DIFF}<tr>"
DIFF="${DIFF} <td> <img src=\"https://raw.githubusercontent.com/commaai/ci-artifacts/${{ env.BRANCH_NAME }}/${A[$i]}.png\"> </td>"
DIFF="${DIFF}</tr>"
DIFF="${DIFF}</table>"
DIFF="${DIFF}</details>"
elif ! compare -fuzz 2% -highlight-color DeepSkyBlue1 -lowlight-color Black -compose Src ${{ github.workspace }}/master_ui_raylib/${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_raylib/${A[$i]}.png composite_diff.png
convert -delay 100 ${{ github.workspace }}/master_ui_raylib/${A[$i]}.png composite_diff.png -loop 0 ${{ github.workspace }}/pr_ui/${A[$i]}_diff.gif
mv ${{ github.workspace }}/master_ui_raylib/${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_raylib
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 "raylib 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_raylib **${{ github.run_id }}**)_ -->
## raylib UI Preview
${{ steps.find_diff.outputs.DIFF }}
comment_tag: run_id_screenshots_raylib
pr_number: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-42
View File
@@ -1,42 +0,0 @@
name: release
on:
schedule:
- cron: '0 9 * * *'
workflow_dispatch:
jobs:
build_masterci:
name: build master-ci
env:
ImageOS: ubuntu24
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 == 'schedule' }}
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: Push master-ci
run: BRANCH=__nightly release/build_stripped.sh
-72
View File
@@ -1,72 +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 submodule update --remote
git add .
- name: update car docs
run: |
export PYTHONPATH="$PWD"
scons -j$(nproc) --minimal opendbc_repo
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
-71
View File
@@ -1,71 +0,0 @@
name: Schedule StarPilot Update
on:
workflow_dispatch:
inputs:
scheduled_date:
description: "Enter the date to update the \"StarPilot\" branch (YYYY-MM-DD)"
required: true
env:
GIT_EMAIL: "91348155+FrogAi@users.noreply.github.com"
GIT_NAME: "James"
TARGET_BRANCH: "StarPilot-Staging"
UPDATE_FILE_PATH: ".github/update_date"
jobs:
schedule_update:
runs-on: ubuntu-latest
steps:
- name: Checkout Target Branch
uses: actions/checkout@v4
with:
ref: ${{ env.TARGET_BRANCH }}
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
fetch-depth: 3
- name: Configure Git Identity
run: |
git config --global user.name "$GIT_NAME"
git config --global user.email "$GIT_EMAIL"
- name: Write Schedule Date
env:
SCHEDULED_DATE: ${{ github.event.inputs.scheduled_date }}
run: |
echo "$SCHEDULED_DATE" > "$UPDATE_FILE_PATH"
git add "$UPDATE_FILE_PATH"
- name: Get Target Commit Data
id: get_target
run: |
TARGET_COMMIT=$(git rev-parse HEAD~1)
AUTHOR_DATE=$(git show -s --format=%aD "$TARGET_COMMIT")
COMMITTER_DATE=$(git show -s --format=%cD "$TARGET_COMMIT")
echo "AUTHOR_DATE=$AUTHOR_DATE" >> "$GITHUB_ENV"
echo "COMMITTER_DATE=$COMMITTER_DATE" >> "$GITHUB_ENV"
echo "TARGET_COMMIT=$TARGET_COMMIT" >> "$GITHUB_ENV"
- name: Create Fixup Commit
id: fixup_commit
run: |
if git diff --cached --quiet; then
echo "No changes detected."
echo "has_changes=false" >> "$GITHUB_OUTPUT"
else
echo "Changes detected. Creating fixup commit."
git commit --fixup="$TARGET_COMMIT"
echo "has_changes=true" >> "$GITHUB_OUTPUT"
fi
- name: Autosquash and Restore Timestamps
if: steps.fixup_commit.outputs.has_changes == 'true'
run: |
GIT_SEQUENCE_EDITOR=: git rebase --autosquash -i HEAD~3
git rebase --exec "GIT_COMMITTER_DATE='$COMMITTER_DATE' git commit --amend --no-edit --date='$AUTHOR_DATE'" HEAD~2
- name: Push Changes
if: steps.fixup_commit.outputs.has_changes == 'true'
run: |
git push origin "$TARGET_BRANCH" --force-with-lease
@@ -1,52 +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
outputs:
duration:
description: 'Duration of the setup process in seconds'
value: ${{ steps.get_duration.outputs.duration }}
runs:
using: "composite"
steps:
- id: start_time
shell: bash
run: echo "START_TIME=$(date +%s)" >> $GITHUB_ENV
- 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
- id: get_duration
shell: bash
run: |
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
echo "Total duration: $DURATION seconds"
echo "duration=$DURATION" >> $GITHUB_OUTPUT
-56
View File
@@ -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 }}
-52
View File
@@ -1,52 +0,0 @@
name: stale
on:
schedule:
- cron: '30 1 * * *'
workflow_dispatch:
env:
DAYS_BEFORE_PR_CLOSE: 7
DAYS_BEFORE_PR_STALE: 24
DAYS_BEFORE_PR_STALE_DRAFT: 30
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 }}
exempt-draft-pr: false
# issue config
days-before-issue-stale: -1 # ignore issues for now
# same as above, but give draft PRs more time
stale_drafts:
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_DRAFT }} 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_DRAFT }}
days-before-pr-close: ${{ env.DAYS_BEFORE_PR_CLOSE }}
exempt-draft-pr: true
# issue config
days-before-issue-stale: -1 # ignore issues for now
-294
View File
@@ -1,294 +0,0 @@
name: tests
on:
push:
branches:
- master
pull_request:
workflow_dispatch:
workflow_call:
inputs:
run_number:
default: '1'
required: true
type: string
concurrency:
group: 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 --durations=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'))
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["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_stripped.sh
- uses: ./.github/workflows/setup-with-retry
- 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"
- name: Check submodules
if: github.repository == 'commaai/openpilot'
timeout-minutes: 3
run: release/check-submodules.sh
build:
runs-on: ${{
(github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["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
if: false # tmp disable due to brew install not working
runs-on: ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-macos-8x14' || 'macos-latest' }}
steps:
- uses: actions/checkout@v4
with:
submodules: true
- run: echo "CACHE_COMMIT_DATE=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d-%H:%M')" >> $GITHUB_ENV
- name: Homebrew cache
uses: ./.github/workflows/auto-cache
with:
path: ~/Library/Caches/Homebrew
key: brew-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
restore-keys: |
brew-macos-${{ env.CACHE_COMMIT_DATE }}
brew-macos
- name: Install dependencies
run: ./tools/mac_setup.sh
env:
PYTHONWARNINGS: default # package install has DeprecationWarnings
HOMEBREW_DISPLAY_INSTALL_TIMES: 1
- run: git lfs pull
- name: Getting scons cache
uses: ./.github/workflows/auto-cache
with:
path: /tmp/scons_cache
key: scons-${{ runner.arch }}-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
restore-keys: |
scons-${{ runner.arch }}-macos-${{ env.CACHE_COMMIT_DATE }}
scons-${{ runner.arch }}-macos
- 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'))
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["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'))
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["ubuntu-24.04"]') }}
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
id: setup-step
- name: Build openpilot
run: ${{ env.RUN }} "scons -j$(nproc)"
- name: Run unit tests
timeout-minutes: ${{ contains(runner.name, 'nsc') && ((steps.setup-step.outputs.duration < 18) && 1 || 2) || 20 }}
run: |
${{ env.RUN }} "source selfdrive/test/setup_xvfb.sh && \
# Pre-compile Python bytecode so each pytest worker doesn't need to
$PYTEST --collect-only -m 'not slow' -qq && \
MAX_EXAMPLES=1 $PYTEST -m 'not slow' && \
chmod -R 777 /tmp/comma_download_cache"
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'))
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["ubuntu-24.04"]') }}
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
id: setup-step
- 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') && ((steps.setup-step.outputs.duration < 18) && 1 || 2) || 20 }}
run: |
${{ env.RUN }} "selfdrive/test/process_replay/test_processes.py -j$(nproc) && \
chmod -R 777 /tmp/comma_download_cache"
- 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: false # TODO: move this to github instead of azure
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"
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'))
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["ubuntu-24.04"]') }}
if: false # FIXME: Started to timeout recently
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
id: setup-step
- name: Build openpilot
run: |
${{ env.RUN }} "scons -j$(nproc)"
- name: Driving test
timeout-minutes: ${{ (steps.setup-step.outputs.duration < 18) && 1 || 2 }}
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_raylib_ui_report:
name: Create raylib UI Report
runs-on: ${{
(github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["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: Create raylib UI Report
run: >
${{ env.RUN }} "PYTHONWARNINGS=ignore &&
source selfdrive/test/setup_xvfb.sh &&
python3 selfdrive/ui/tests/test_ui/raylib_screenshots.py"
- name: Upload Raylib UI Report
uses: actions/upload-artifact@v4
with:
name: raylib-report-${{ inputs.run_number || '1' }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }}
path: selfdrive/ui/tests/test_ui/raylib_report/screenshots
create_mici_raylib_ui_report:
name: Create mici raylib UI Report
runs-on: ${{
(github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["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: Create mici raylib UI Report
run: >
${{ env.RUN }} "PYTHONWARNINGS=ignore &&
source selfdrive/test/setup_xvfb.sh &&
WINDOWED=1 python3 selfdrive/ui/tests/diff/replay.py"
- name: Upload Raylib UI Report
uses: actions/upload-artifact@v4
with:
name: mici-raylib-report-${{ inputs.run_number || '1' }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }}
path: selfdrive/ui/tests/diff/report
@@ -1,107 +0,0 @@
name: Update StarPilot Branch
on:
schedule:
- cron: "0 18 * * 6"
env:
BRANCH_STARPILOT: StarPilot
BRANCH_PREVIOUS: StarPilot-Previous
BRANCH_STAGING: StarPilot-Staging
GIT_EMAIL: "91348155+FrogAi@users.noreply.github.com"
GIT_NAME: "James"
GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
TZ: America/Phoenix
UPDATE_FILE: .github/update_date
jobs:
check_update:
runs-on: ubuntu-latest
outputs:
update_due: ${{ steps.check_update.outputs.update_due }}
scheduled_date: ${{ steps.check_update.outputs.scheduled_date }}
steps:
- name: Check Update Status
id: check_update
env:
REPO_NAME: ${{ github.repository }}
run: |
URL="https://raw.githubusercontent.com/$REPO_NAME/$BRANCH_STAGING/$UPDATE_FILE"
STATUS=$(curl -o /dev/null -s -w "%{http_code}\n" "$URL")
if [ "$STATUS" != "200" ]; then
echo "update_due=false" >> "$GITHUB_OUTPUT"
exit 0
fi
SCHEDULED_DATE=$(curl -s "$URL")
CURRENT_DATE=$(TZ="$TZ" date +%F)
if [ "$SCHEDULED_DATE" == "$CURRENT_DATE" ]; then
echo "update_due=true" >> "$GITHUB_OUTPUT"
echo "scheduled_date=$SCHEDULED_DATE" >> "$GITHUB_OUTPUT"
else
echo "update_due=false" >> "$GITHUB_OUTPUT"
fi
update_branch:
needs: check_update
if: ${{ needs.check_update.outputs.update_due == 'true' }}
runs-on: ubuntu-latest
steps:
- name: Checkout Staging
uses: actions/checkout@v4
with:
ref: ${{ env.BRANCH_STAGING }}
fetch-depth: 0
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
- name: Configure Git Identity
run: |
git config --global user.name "$GIT_NAME"
git config --global user.email "$GIT_EMAIL"
- name: Update README and Cleanup
env:
SCHEDULED_DATE: ${{ needs.check_update.outputs.scheduled_date }}
run: |
DAY=$(TZ="$TZ" date +'%d' | sed 's/^0//')
case "$DAY" in
1|21|31) SUFFIX="st" ;;
2|22) SUFFIX="nd" ;;
3|23) SUFFIX="rd" ;;
*) SUFFIX="th" ;;
esac
MONTH=$(TZ="$TZ" date +'%B')
YEAR=$(TZ="$TZ" date +'%Y')
DATE_FMT="${MONTH} ${DAY}${SUFFIX}, ${YEAR}"
DATE_ESCAPED=$(printf '%s' "$DATE_FMT" | sed -E 's/ /%20/g; s/,/%2C/g')
sed -i -E "s|(Last%20Updated-)[^-)]*|\1${DATE_ESCAPED}|g" README.md
git rm -f "$UPDATE_FILE"
git add README.md
git commit -m "Updated README date to ${DATE_FMT}"
git reset --soft HEAD~2
ORIGINAL_MSG=$(git log -1 --pretty=%B HEAD)
COMMIT_PHX=$(TZ="$TZ" date -d "$SCHEDULED_DATE 12:00" +"%Y-%m-%dT%H:%M:%S %z")
GIT_COMMITTER_DATE="$COMMIT_PHX" GIT_AUTHOR_DATE="$COMMIT_PHX" git commit -m "$ORIGINAL_MSG"
- name: Wait Until Noon ${{ env.TZ }}
run: |
NOW=$(TZ="$TZ" date +%s)
TARGET=$(TZ="$TZ" date -d "12:00" +%s)
if [ "$NOW" -lt "$TARGET" ]; then
sleep $((TARGET - NOW))
fi
- name: Push and Sync Branches
run: |
git push origin "$BRANCH_STAGING" --force
git fetch origin "$BRANCH_STARPILOT:$BRANCH_STARPILOT"
git push origin "$BRANCH_STARPILOT:$BRANCH_PREVIOUS" --force
git push origin "$BRANCH_STAGING:$BRANCH_STARPILOT" --force
-95
View File
@@ -1,95 +0,0 @@
name: Update Tinygrad
on:
workflow_dispatch:
inputs:
runner:
description: "Select runner"
type: choice
options:
- c3
- c3x
default: "c3"
required: true
env:
GIT_EMAIL: "91348155+FrogAi@users.noreply.github.com"
GIT_NAME: "James"
GITLAB_REPO_DIR: "StarPilot-Resources"
GITLAB_URL: "gitlab.com/FrogAi/StarPilot-Resources.git"
OPENPILOT_DIR: "/data/openpilot"
jobs:
update_tinygrad:
runs-on: [self-hosted, "${{ inputs.runner }}"]
steps:
- name: Get Version
id: get_version
run: |
VERSION=$(grep -oP '^VERSION\s*=\s*"\K[^"]+' "$OPENPILOT_DIR/starpilot/assets/model_manager.py")
echo "VERSION=$VERSION"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Setup Workspace and Clone GitLab
id: setup
env:
GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }}
run: |
WORK_DIR="$RUNNER_TEMP/starpilot_tinygrad"
rm -rf "$WORK_DIR" && mkdir -p "$WORK_DIR"
echo "work_dir=$WORK_DIR" >> "$GITHUB_OUTPUT"
cd "$WORK_DIR"
git clone --depth 1 --branch Tinygrad "https://oauth2:${GITLAB_TOKEN}@$GITLAB_URL"
- name: Create Tinygrad Archive
working-directory: ${{ env.OPENPILOT_DIR }}
env:
WORK_DIR: ${{ steps.setup.outputs.work_dir }}
VERSION: ${{ steps.get_version.outputs.version }}
run: |
set -euo pipefail
ARCHIVE_DEST="$WORK_DIR/$GITLAB_REPO_DIR"
ARCHIVE_NAME="Tinygrad_$VERSION.tar.gz"
DUMMY_DIR=$(mktemp -d)
touch "$DUMMY_DIR/SConscript"
tar -czf "$ARCHIVE_DEST/$ARCHIVE_NAME" \
--exclude="*.a" \
--exclude="*.o" \
--exclude="*.onnx" \
--exclude="*__pycache__*" \
--exclude="*tests*" \
--exclude="selfdrive/modeld/SConscript" \
selfdrive/modeld tinygrad_repo \
-C "$DUMMY_DIR" \
--transform 's|^SConscript$|selfdrive/modeld/SConscript|' \
SConscript
rm -rf "$DUMMY_DIR"
- name: Push Updated Tinygrad
working-directory: ${{ steps.setup.outputs.work_dir }}/${{ env.GITLAB_REPO_DIR }}
env:
VERSION: ${{ steps.get_version.outputs.version }}
run: |
git config user.name "$GIT_NAME"
git config user.email "$GIT_EMAIL"
git add Tinygrad_*.tar.gz
if git diff --staged --quiet; then
echo "No changes to commit."
else
git commit -m "Updated Tinygrad: $VERSION"
git push origin Tinygrad
fi
- name: Cleanup Temporary Files
if: always()
env:
WORK_DIR: ${{ steps.setup.outputs.work_dir }}
run: |
rm -rf "$WORK_DIR"
+26 -65
View File
@@ -13,17 +13,13 @@ venv/
a.out a.out
.hypothesis .hypothesis
.cache/ .cache/
.host_runtime/ bin/
.comma_sysroot/
.venv-linux-arm64/
compiledmodels/
/docs_site/
*.mp4 *.mp4
*.dylib *.dylib
*.DSYM *.DSYM
*.d *.d
*.pem
*.pyc *.pyc
*.pyo *.pyo
.*.swp .*.swp
@@ -43,94 +39,59 @@ compiledmodels/
*.mo *.mo
*_pyx.cpp *_pyx.cpp
*.stats *.stats
*.pkl
*.pkl*
config.json config.json
clcache
compile_commands.json compile_commands.json
compare_runtime*.html compare_runtime*.html
selfdrive/modeld/models/tg_compiled_flags.json
# build artifacts
docs_site/
selfdrive/pandad/pandad
cereal/services.h cereal/services.h
cereal/gen cereal/gen
cereal/messaging/bridge
selfdrive/ui/translations/tmp selfdrive/ui/translations/tmp
selfdrive/car/tests/cars_dump selfdrive/car/tests/cars_dump
system/camerad/camerad
system/camerad/test/ae_gray_test system/camerad/test/ae_gray_test
selfdrive/ui/ui.macos
selfdrive/ui/ui.larch64
.coverage* .coverage*
coverage.xml coverage.xml
htmlcov htmlcov
pandaextra
.mypy_cache/
flycheck_*
cppcheck_report.txt
comma*.sh
selfdrive/modeld/models/*.pkl
!selfdrive/modeld/models/driving_vision_tinygrad.pkl
!selfdrive/modeld/models/driving_policy_tinygrad.pkl
!selfdrive/modeld/models/driving_vision_metadata.pkl
!selfdrive/modeld/models/driving_policy_metadata.pkl
!selfdrive/modeld/models/dmonitoring_model_tinygrad.pkl
!selfdrive/modeld/models/dmonitoring_model_metadata.pkl
!selfdrive/modeld/models/warp_1928x1208_tinygrad.pkl
!selfdrive/modeld/models/warp_1344x760_tinygrad.pkl
!selfdrive/modeld/models/dm_warp_1928x1208_tinygrad.pkl
!selfdrive/modeld/models/dm_warp_1344x760_tinygrad.pkl
# openpilot log files # 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
# Keep prebuilt runtime artifacts trackable
!cereal/messaging/bridge
!system/camerad/camerad
!system/loggerd/loggerd
!system/loggerd/encoderd
!system/loggerd/bootlog
!selfdrive/pandad/pandad
!cereal/services.h
!cereal/libcereal.a
!cereal/libsocketmaster.a
!common/params_pyx.so
!common/params_pyx.cpp
!common/transformations/transformations.so
!selfdrive/modeld/models/commonmodel_pyx.so
!selfdrive/pandad/pandad_api_impl.so
!selfdrive/controls/lib/lateral_mpc_lib/c_generated_code/acados_ocp_solver_pyx.so
!selfdrive/controls/lib/lateral_mpc_lib/c_generated_code/libacados_ocp_solver_lat.so
!selfdrive/controls/lib/longitudinal_mpc_lib/c_generated_code/acados_ocp_solver_pyx.so
!selfdrive/controls/lib/longitudinal_mpc_lib/c_generated_code/libacados_ocp_solver_long.so
!common/libcommon.a
!msgq_repo/msgq/ipc_pyx.so
!msgq_repo/msgq/visionipc/visionipc_pyx.so
!rednose_repo/rednose/helpers/ekf_sym_pyx.so
!panda/board/obj/
!panda/board/obj/**
+1
View File
@@ -0,0 +1 @@
3.12.13
-1
View File
@@ -4,6 +4,5 @@
"ms-vscode.cpptools", "ms-vscode.cpptools",
"elagil.pre-commit-helper", "elagil.pre-commit-helper",
"charliermarsh.ruff", "charliermarsh.ruff",
"openai.chatgpt",
] ]
} }
+3
View File
@@ -52,6 +52,9 @@
"type": "lldb", "type": "lldb",
"request": "attach", "request": "attach",
"pid": "${command:pickMyProcess}", "pid": "${command:pickMyProcess}",
"sourceMap": {
".": "${workspaceFolder}/opendbc/safety"
},
"initCommands": [ "initCommands": [
"script import time; time.sleep(3)" "script import time; time.sleep(3)"
] ]
+83
View File
@@ -0,0 +1,83 @@
#!/bin/env sh
persist_dir=/persist
target_dir=${persist_dir}/comma
# Change target dir from sunnylink to comma to make this no longer a test
# Function to remount /persist as read-only
cleanup() {
echo "Remounting ${persist_dir} as read-only..."
sudo mount -o remount,ro ${persist_dir}
}
# Function to check and backup existing keys
backup_keys() {
if [ -f "id_rsa" ] || [ -f "id_rsa.pub" ]; then
timestamp=$(date +%s)
backup_base="id_rsa_backup_$timestamp"
backup_private="$backup_base"
backup_public="${backup_base}.pub"
# Ensure we're not overwriting an existing backup
counter=0
while [ -f "$backup_private" ] || [ -f "$backup_public" ]; do
counter=$((counter + 1))
backup_private="${backup_base}_$counter"
backup_public="${backup_base}_$counter.pub"
done
# Backup the keys
cp id_rsa "$backup_private"
cp id_rsa.pub "$backup_public"
# Verify the backup
original_private_hash=$(sha256sum id_rsa | cut -d ' ' -f 1)
backup_private_hash=$(sha256sum "$backup_private" | cut -d ' ' -f 1)
original_public_hash=$(sha256sum id_rsa.pub | cut -d ' ' -f 1)
backup_public_hash=$(sha256sum "$backup_public" | cut -d ' ' -f 1)
if [ "$original_private_hash" = "$backup_private_hash" ] && [ "$original_public_hash" = "$backup_public_hash" ]; then
echo "Backup verified successfully."
# Safe to delete original keys after successful backup verification
else
echo "Backup verification failed. Aborting operation."
exit 1
fi
echo "Existing keys backed up as $backup_private and $backup_public"
fi
}
# Trap any signal that exits the script to run cleanup function
trap cleanup EXIT
# Remount /persist as read-write
sudo mount -o remount,rw ${persist_dir}
# Ensure the directory exists
mkdir -p ${target_dir}
cd ${target_dir}
# Check for and backup existing keys
#backup_keys
# Generate new keys
if ! ssh-keygen -t rsa -b 4096 -m PEM -f id_rsa -N ''; then
echo "Failed to generate new RSA keys. Exiting..."
exit 1
fi
# Convert the generated SSH public key to PEM format and store it temporarily
if ! openssl rsa -pubout -in id_rsa -out id_rsa.pub -outform PEM; then
echo "Failed to convert the public key to PEM format. Exiting..."
exit 1
fi
# Display the public key
echo "Displaying the public key:"
cat id_rsa.pub
# Cleanup will be called automatically due to trap on EXIT
#echo "Operation completed successfully. System will reboot now."
#sudo reboot
+1288
View File
File diff suppressed because it is too large Load Diff
+30 -6
View File
@@ -1,14 +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
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}/
ENV UV_BIN="/home/batman/.local/bin/" ENV UV_BIN="/home/$USER/.local/bin/"
ENV PATH="$UV_BIN:$PATH" ENV VIRTUAL_ENV=${OPENPILOT_PATH}/.venv
RUN UV_PROJECT_ENVIRONMENT=$VIRTUAL_ENV uv run scons --cache-readonly -j$(nproc) 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 '*'
-81
View File
@@ -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
-269
View File
@@ -1,269 +0,0 @@
def retryWithDelay(int maxRetries, int delay, Closure body) {
for (int i = 0; i < maxRetries; i++) {
try {
return body()
} catch (Exception e) {
sleep(delay)
}
}
throw Exception("Failed after ${maxRetries} retries")
}
def device(String ip, String step_label, String cmd) {
withCredentials([file(credentialsId: 'id_rsa', variable: 'key_file')]) {
def ssh_cmd = """
ssh -o ConnectTimeout=5 -o ServerAliveInterval=5 -o ServerAliveCountMax=2 -o BatchMode=yes -o StrictHostKeyChecking=no -i ${key_file} 'comma@${ip}' exec /usr/bin/bash <<'END'
set -e
export TERM=xterm-256color
shopt -s huponexit # kill all child processes when the shell exits
export CI=1
export PYTHONWARNINGS=error
export LOGPRINT=debug
export TEST_DIR=${env.TEST_DIR}
export SOURCE_DIR=${env.SOURCE_DIR}
export GIT_BRANCH=${env.GIT_BRANCH}
export GIT_COMMIT=${env.GIT_COMMIT}
export CI_ARTIFACTS_TOKEN=${env.CI_ARTIFACTS_TOKEN}
export GITHUB_COMMENTS_TOKEN=${env.GITHUB_COMMENTS_TOKEN}
export AZURE_TOKEN='${env.AZURE_TOKEN}'
# only use 1 thread for tici tests since most require HIL
export PYTEST_ADDOPTS="-n0 -s"
export GIT_SSH_COMMAND="ssh -i /data/gitkey"
source ~/.bash_profile
if [ -f /TICI ]; then
source /etc/profile
rm -rf /tmp/tmp*
rm -rf ~/.commacache
rm -rf /dev/shm/*
rm -rf /dev/tmp/tmp*
if ! systemctl is-active --quiet systemd-resolved; then
echo "restarting resolved"
sudo systemctl start systemd-resolved
sleep 3
fi
# restart aux USB
if [ -e /sys/bus/usb/drivers/hub/3-0:1.0 ]; then
echo "restarting aux usb"
echo "3-0:1.0" | sudo tee /sys/bus/usb/drivers/hub/unbind
sleep 0.5
echo "3-0:1.0" | sudo tee /sys/bus/usb/drivers/hub/bind
fi
fi
if [ -f /data/openpilot/launch_env.sh ]; then
source /data/openpilot/launch_env.sh
fi
ln -snf ${env.TEST_DIR} /data/pythonpath
cd ${env.TEST_DIR} || true
time ${cmd}
END"""
sh script: ssh_cmd, label: step_label
}
}
def deviceStage(String stageName, String deviceType, List extra_env, def steps) {
stage(stageName) {
if (currentBuild.result != null) {
return
}
if (isReplay()) {
error("REPLAYING TESTS IS NOT ALLOWED. FIX THEM INSTEAD.")
}
def extra = extra_env.collect { "export ${it}" }.join('\n');
def branch = env.BRANCH_NAME ?: 'master';
def gitDiff = sh returnStdout: true, script: 'curl -s -H "Authorization: Bearer ${GITHUB_COMMENTS_TOKEN}" https://api.github.com/repos/commaai/openpilot/compare/master...${GIT_BRANCH} | jq .files[].filename || echo "/"', label: 'Getting changes'
lock(resource: "", label: deviceType, inversePrecedence: true, variable: 'device_ip', quantity: 1, resourceSelectStrategy: 'random') {
docker.image('ghcr.io/commaai/alpine-ssh').inside('--user=root') {
timeout(time: 35, unit: 'MINUTES') {
retry (3) {
def date = sh(script: 'date', returnStdout: true).trim();
device(device_ip, "set time", "date -s '" + date + "'")
device(device_ip, "git checkout", extra + "\n" + readFile("selfdrive/test/setup_device_ci.sh"))
}
steps.each { item ->
def name = item[0]
def cmd = item[1]
def args = item[2]
def diffPaths = args.diffPaths ?: []
def cmdTimeout = args.timeout ?: 9999
if (branch != "master" && !branch.contains("__jenkins_loop_") && diffPaths && !hasPathChanged(gitDiff, diffPaths)) {
println "Skipping ${name}: no changes in ${diffPaths}."
return
} else {
timeout(time: cmdTimeout, unit: 'SECONDS') {
device(device_ip, name, cmd)
}
}
}
}
}
}
}
}
def hasPathChanged(String gitDiff, List<String> paths) {
for (path in paths) {
if (gitDiff.contains(path)) {
return true
}
}
return false
}
def isReplay() {
def replayClass = "org.jenkinsci.plugins.workflow.cps.replay.ReplayCause"
return currentBuild.rawBuild.getCauses().any{ cause -> cause.toString().contains(replayClass) }
}
def setupCredentials() {
withCredentials([
string(credentialsId: 'azure_token', variable: 'AZURE_TOKEN'),
]) {
env.AZURE_TOKEN = "${AZURE_TOKEN}"
}
withCredentials([
string(credentialsId: 'ci_artifacts_pat', variable: 'CI_ARTIFACTS_TOKEN'),
]) {
env.CI_ARTIFACTS_TOKEN = "${CI_ARTIFACTS_TOKEN}"
}
withCredentials([
string(credentialsId: 'post_comments_github_pat', variable: 'GITHUB_COMMENTS_TOKEN'),
]) {
env.GITHUB_COMMENTS_TOKEN = "${GITHUB_COMMENTS_TOKEN}"
}
}
def step(String name, String cmd, Map args = [:]) {
return [name, cmd, args]
}
node {
env.CI = "1"
env.PYTHONWARNINGS = "error"
env.TEST_DIR = "/data/openpilot"
env.SOURCE_DIR = "/data/openpilot_source/"
setupCredentials()
env.GIT_BRANCH = checkout(scm).GIT_BRANCH
env.GIT_COMMIT = checkout(scm).GIT_COMMIT
def excludeBranches = ['__nightly', 'devel', 'devel-staging', 'release3', 'release3-staging',
'release-tici', 'release-tizi', 'release-tizi-staging', 'testing-closet*', 'hotfix-*']
def excludeRegex = excludeBranches.join('|').replaceAll('\\*', '.*')
if (env.BRANCH_NAME != 'master' && !env.BRANCH_NAME.contains('__jenkins_loop_')) {
properties([
disableConcurrentBuilds(abortPrevious: true)
])
}
try {
if (env.BRANCH_NAME == 'devel-staging') {
deviceStage("build release-tizi-staging", "tizi-needs-can", [], [
step("build release-tizi-staging", "RELEASE_BRANCH=release-tizi-staging $SOURCE_DIR/release/build_release.sh"),
])
}
if (env.BRANCH_NAME == '__nightly') {
parallel (
'nightly': {
deviceStage("build nightly", "tizi-needs-can", [], [
step("build nightly", "RELEASE_BRANCH=nightly $SOURCE_DIR/release/build_release.sh"),
])
},
'nightly-dev': {
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"),
])
},
)
}
if (!env.BRANCH_NAME.matches(excludeRegex)) {
parallel (
'onroad tests': {
deviceStage("onroad", "tizi-needs-can", ["UNSAFE=1"], [
step("build openpilot", "cd system/manager && ./build.py"),
step("check dirty", "release/check-dirty.sh"),
step("onroad tests", "pytest selfdrive/test/test_onroad.py -s", [timeout: 60]),
])
},
'HW + Unit Tests': {
deviceStage("tizi-hardware", "tizi-common", ["UNSAFE=1"], [
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 encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py", [diffPaths: ["system/loggerd/"]]),
step("test manager", "pytest system/manager/test/test_manager.py"),
])
},
'loopback': {
deviceStage("loopback", "tizi-loopback", ["UNSAFE=1"], [
step("build openpilot", "cd system/manager && ./build.py"),
step("test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"),
])
},
'camerad OX03C10': {
deviceStage("OX03C10", "tizi-ox03c10", ["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 OS04C10': {
deviceStage("OS04C10", "tici-os04c10", ["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"),
])
},
'sensord': {
deviceStage("LSM + MMC", "tizi-lsmc", ["UNSAFE=1"], [
step("build", "cd system/manager && ./build.py"),
step("test sensord", "pytest system/sensord/tests/test_sensord.py"),
])
},
'replay': {
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("model replay", "selfdrive/test/process_replay/model_replay.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]),
])
},
'tizi': {
deviceStage("tizi", "tizi", ["UNSAFE=1"], [
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 spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"),
step("test amp", "pytest system/hardware/tici/tests/test_amplifier.py"),
// TODO: enable once new AGNOS is available
// step("test esim", "pytest system/hardware/tici/tests/test_esim.py"),
step("test qcomgpsd", "pytest system/qcomgpsd/tests/test_qcomgpsd.py", [diffPaths: ["system/qcomgpsd/"]]),
])
},
)
}
} catch (Exception e) {
currentBuild.result = 'FAILED'
throw e
}
}
+21
View File
@@ -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
+62 -63
View File
@@ -1,75 +1,74 @@
# StarPilot ![](https://user-images.githubusercontent.com/47793918/233812617-beab2e71-57b9-479e-8bff-c3931347ca40.png)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/firestar5683/StarPilot) ## 🌞 What is sunnypilot?
[![Discord](https://img.shields.io/discord/1137853399715549214?label=Discord)](https://firestar.link/discord) [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.
[![Last Updated](https://img.shields.io/github/last-commit/firestar5683/StarPilot/StarPilot)](https://github.com/firestar5683/StarPilot)
[![Wiki](https://img.shields.io/badge/Wiki-StarPilot-blue?logo=wiki)](https://wiki.firestar.link)
**StarPilot** is a custom fork of [comma.ai's openpilot](https://comma.ai/openpilot), ## 💭 Join our Community Forum
an open source driver assistance system. 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/
Openpilot provides
* Automated Lane Centering
* Adaptive Cruise Control
* Lane Change Assist
* Driver Monitoring *without wheel nags*
StarPilot adds support for many GM vehicles along with improved tuning,
especially for radar-less (camera only) vehicles.
StarPilot is built off of [StarPilot](https://github.com/FrogAi/StarPilot)
and supports the major features StarPilot offers.
StarPilot has a vibrant, welcoming community [discord](https://firestar.link/discord).
Stop by to chat or ask questions!
## Documentation ## Documentation
https://docs.sunnypilot.ai/ is your one stop shop for everything from features to installation to FAQ about the sunnypilot
Please see [https://wiki.firestar.link](https://wiki.firestar.link) for hardware lists, ## 🚘 Running on a dedicated device in a car
installation guides, and software configuration. 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).
## Features ## Installation
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).
* Full support for Comma C3, C3X, and C4 ## 🎆 Pull Requests
* C4 is currently in release testing. Join our fleet of C4 testers! We welcome both pull requests and issues on GitHub. Bug fixes are encouraged.
* Model switcher with all of comma's tinygrad driving models
* Special longitudinal planner tuning for VoACC (visual only, radar-less) vehicles
* Galaxy: StarPilot's portal to configure your comma device using your phone from anywhere.
Download models, change settings, update software, visualize live model outputs for tuning.
* Always On Lateral (full time steering assist)*
* Speed Limit Controller*
* Learning Curve Speed Controller*
* Conditional Experimental Mode (CEM)*
* Driving Profiles*
* Custom themes*
* Alert Volume Controller*
* Comma Pedal Interceptor support*
* Toyota SDSU support*
* ZSS support*
* High quality dashcam recordings*
* Enhanced tuning for CEM (dynamic experimental mode switching)
\* [Inherited from StarPilot](https://github.com/FrogAi/StarPilot#openpilot-vs-starpilot) Pull requests should be against the most current `master` branch.
## GM-only Features ## 📊 User Data
* Increased LKAS fault resiliency By default, sunnypilot uploads the driving data to comma servers. You can also access your data through [comma connect](https://connect.comma.ai/).
* ASCM_INT and SASCM support
* Custom lateral torque controller, with special tuning for Bolts
* 50% extra torque on 2017 Chevy Bolt
* Improved lateral and longitudinal tuning
* Dashboard cruise control display speed spoofing for vehicles with pedal interceptor
* Extra steering wheel button functionality for vehicles with pedal interceptor
* Optional toggle to boot comma when remote starting your vehicle
## Developer Features sunnypilot is open source software. The user is free to disable data collection if they wish to do so.
* Native and cross compilation for Windows, Mac, and Ubuntu sunnypilot logs the road-facing camera, CAN, GPS, IMU, magnetometer, thermal sensors, crashes, and operating system logs.
* Custom AGNOS to support C3, C3X, and C4 The driver-facing camera and microphone are only logged if you explicitly opt-in in settings.
* To run UI on PC:
* `./c3` for large UI 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.
* `./c4` for small UI
* `./build` to produce cross compiled binaries for comma devices. ## Licensing
Uses your comma's sysroot/toolchain
* Toggle: "Use Precompiled Binaries" to allow switching between fast boot / editable builds 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.
* Custom long maneuver tests, specifically designed for regen-only vehicles
The original openpilot license notice, including comma.ais 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.
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.
<h3>GitHub Sponsor</h3>
<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>
<h3>PayPal</h3>
<a href="https://paypal.me/sunnyhaibin0850" target="_blank">
<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" />
</a>
<br></br>
Your continuous love and support are greatly appreciated! Enjoy 🥰
<span>-</span> Jason, Founder of sunnypilot
+15
View File
@@ -1,3 +1,18 @@
Version 0.11.1 (2026-04-22)
========================
* New driver monitoring model
* Improved image processing pipeline for driver camera
* Rivian R1S and R1T 2025 support thanks to lukasloetkolben!
Version 0.11.0 (2026-03-17)
========================
* New driving model #36798
* Fully trained using a learned simulator
* 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!
Version 0.10.3 (2025-12-17) Version 0.10.3 (2025-12-17)
======================== ========================
* New driving model #36249 * New driving model #36249
-510
View File
@@ -1,510 +0,0 @@
import os
import shutil
import subprocess
import sys
import sysconfig
import platform
import numpy as np
import SCons.Errors
SCons.Warnings.warningAsException(True)
# pending upstream fix - https://github.com/SCons/scons/issues/4461
#SetOption('warn', 'all')
force_tici = os.environ.get("SP_FORCE_TICI", "").lower() in {"1", "true", "yes", "on"}
TICI = os.path.isfile('/TICI') or force_tici
AGNOS = TICI
Decider('MD5-timestamp')
SetOption('num_jobs', max(1, int(os.cpu_count()/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('--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('--mutation',
action='store_true',
help='generate mutation-ready code')
AddOption('--minimal',
action='store_false',
dest='extras',
default=os.path.exists(File('#.lfsconfig').abspath), # minimal by default on release branch (where there's no LFS)
help='the minimum build to run openpilot. no tests, tools, etc.')
AddOption('--extras',
action='store_true',
dest='extras',
default=os.path.exists(File('#.lfsconfig').abspath),
help='build optional tools/tests even when minimal is the default')
def maybe_delegate_to_laptop_device_builder() -> None:
if platform.system() != "Darwin":
return
if os.environ.get("SP_FORCE_ARCH"):
return
if os.environ.get("SP_SKIP_CONTAINER_REEXEC"):
return
if os.environ.get("SP_DISABLE_AUTO_DEVICE_SCONS", "").lower() in {"1", "true", "yes", "on"}:
return
basedir = Dir("#").abspath
sysroot_dir = os.environ.get("COMMA_SYSROOT_DIR", os.path.join(basedir, ".comma_sysroot"))
required_sysroot_dirs = (
"usr/local/lib",
"lib/aarch64-linux-gnu",
"usr/lib/aarch64-linux-gnu",
"system/vendor/lib64",
)
if not all(os.path.isdir(os.path.join(sysroot_dir, p)) for p in required_sysroot_dirs):
return
docker_bin = shutil.which("docker")
if docker_bin is None:
mac_docker = "/Applications/Docker.app/Contents/Resources/bin/docker"
if os.path.isfile(mac_docker):
docker_bin = mac_docker
if docker_bin is None and shutil.which("podman") is None:
return
builder = os.path.join(basedir, "scripts", "laptop_device_build.sh")
if not os.path.isfile(builder):
return
print(f"Auto-routing scons to laptop device build (sysroot: {sysroot_dir})", flush=True)
env = os.environ.copy()
env["SP_SKIP_CONTAINER_REEXEC"] = "1"
env.setdefault("COMMA_SYSROOT_DIR", sysroot_dir)
if docker_bin is not None and shutil.which("docker") is None:
docker_dir = os.path.dirname(docker_bin)
env["PATH"] = f"{docker_dir}:{env.get('PATH', '')}"
cmd = [builder, "build", *sys.argv[1:]]
raise SystemExit(subprocess.call(cmd, cwd=basedir, env=env))
maybe_delegate_to_laptop_device_builder()
## Architecture name breakdown (arch)
## - larch64: linux tici aarch64
## - 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()
forced_arch = os.environ.get("SP_FORCE_ARCH")
if forced_arch:
arch = forced_arch
elif platform.system() == "Darwin":
arch = "Darwin"
brew_prefix = subprocess.check_output(['brew', '--prefix'], encoding='utf8').strip()
elif arch == "aarch64" and AGNOS:
arch = "larch64"
assert arch in ["larch64", "aarch64", "x86_64", "Darwin"]
# Homebrew llvm can shadow Apple clang and break macOS SDK header resolution.
# Use the system toolchain explicitly on macOS for reliable local builds.
cc = '/usr/bin/clang' if arch == "Darwin" else 'clang'
cxx = '/usr/bin/clang++' if arch == "Darwin" else 'clang++'
ar = '/usr/bin/ar' if arch == "Darwin" else 'ar'
ranlib = '/usr/bin/ranlib' if arch == "Darwin" else 'ranlib'
lenv = {
"PATH": os.environ['PATH'],
"PYTHONPATH": ":".join([
Dir("#").abspath,
Dir("#third_party/acados").abspath,
Dir("#opendbc_repo").abspath,
]),
"ACADOS_SOURCE_DIR": Dir("#third_party/acados").abspath,
"ACADOS_PYTHON_INTERFACE_PATH": Dir("#third_party/acados/acados_template").abspath,
"TERA_PATH": Dir("#").abspath + f"/third_party/acados/{arch}/t_renderer"
}
# Allow callers to override cache/temp dirs used by subprocesses (e.g. tinygrad model compilation).
for key in ("HOME", "TMPDIR", "XDG_CACHE_HOME", "CACHEDB"):
if key in os.environ:
lenv[key] = os.environ[key]
rpath = []
arch_ldflags = []
def tici_libpath(path: str) -> str:
tici_sysroot = os.environ.get("SP_TICI_SYSROOT", "").strip().rstrip("/")
if arch != "larch64" or not tici_sysroot or not path.startswith("/"):
return path
return os.path.join(tici_sysroot, path.lstrip("/"))
if arch == "larch64":
cpppath = [
"#third_party/opencl/include",
tici_libpath("/usr/local/include"),
tici_libpath("/usr/include"),
tici_libpath("/usr/include/aarch64-linux-gnu"),
]
libpath = [
tici_libpath("/usr/local/lib"),
tici_libpath("/system/vendor/lib64"),
f"#third_party/acados/{arch}/lib",
]
libpath += [
"#third_party/libyuv/larch64/lib",
tici_libpath("/lib/aarch64-linux-gnu"),
tici_libpath("/usr/lib/aarch64-linux-gnu")
]
cflags = ["-D__TICI__", "-DQCOM2", "-mcpu=cortex-a57"]
cxxflags = ["-D__TICI__", "-DQCOM2", "-mcpu=cortex-a57"]
arch_ldflags += [
f"-Wl,-rpath-link,{tici_libpath('/usr/local/lib')}",
f"-Wl,-rpath-link,{tici_libpath('/lib/aarch64-linux-gnu')}",
f"-Wl,-rpath-link,{tici_libpath('/usr/lib/aarch64-linux-gnu')}",
f"-Wl,-rpath-link,{tici_libpath('/system/vendor/lib64')}",
f"-Wl,-rpath-link,{tici_libpath('/vendor/lib64')}",
]
# On non-aarch64 hosts (e.g. Docker on macOS), force clang cross-targeting.
if platform.machine() not in ("aarch64", "arm64"):
cross_target = os.environ.get("SP_CROSS_TARGET", "aarch64-linux-gnu")
cflags += [f"--target={cross_target}"]
cxxflags += [f"--target={cross_target}"]
arch_ldflags += [f"--target={cross_target}"]
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",
]
# Linux
else:
libpath = [
f"#third_party/acados/{arch}/lib",
f"#third_party/libyuv/{arch}/lib",
"/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 = []
ldflags += arch_ldflags
# AGNOS devices are memory-constrained during on-device C++ compiles.
# Building without debug symbols dramatically reduces peak clang memory and
# prevents lowmemorykiller SIGKILLs (Error -9) on large translation units.
use_debug_symbols = os.environ.get("SP_FORCE_DEBUG_SYMBOLS", "").lower() in {"1", "true", "yes", "on"}
debug_flag = "-g" if (not AGNOS or use_debug_symbols) else "-g0"
# 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=lenv,
CCFLAGS=[
debug_flag,
"-fPIC",
"-O2",
"-Wunused",
"-Werror",
"-Wshadow",
"-Wno-unknown-warning-option",
"-Wno-inconsistent-missing-override",
"-Wno-c99-designator",
"-Wno-reorder-init-list",
"-Wno-vla-cxx-extension",
] + cflags + ccflags,
CPPPATH=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",
"#msgq",
],
CC=cc,
CXX=cxx,
AR=ar,
RANLIB=ranlib,
LINKFLAGS=ldflags,
RPATH=rpath,
CFLAGS=["-std=gnu11"] + cflags,
CXXFLAGS=["-std=c++1z"] + cxxflags,
LIBPATH=libpath + [
"#msgq_repo",
"#third_party",
"#selfdrive/pandad",
"#common",
"#rednose/helpers",
],
CYTHONCFILESUFFIX=".cpp",
COMPILATIONDB_USE_ABSPATH=True,
REDNOSE_ROOT="#",
tools=["default", "cython", "compilation_db", "rednose_filter"],
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
)
if arch == "Darwin":
# RPATH is not supported on macOS, instead use the linker flags
darwin_rpath_link_flags = [f"-Wl,-rpath,{path}" for path in env["RPATH"]]
env["LINKFLAGS"] += darwin_rpath_link_flags
env.CompilationDatabase('compile_commands.json')
# Setup cache dir
cache_dir = os.environ.get("SP_SCONS_CACHE_DIR", "").strip()
if not cache_dir:
cache_dir = '/data/scons_cache' if AGNOS else '/tmp/scons_cache'
CacheDir(cache_dir)
Clean(["."], cache_dir)
node_interval = 5
node_count = 0
def progress_function(node):
global node_count
node_count += node_interval
sys.stderr.write("progress: %d\n" % node_count)
if os.environ.get('SCONS_PROGRESS'):
Progress(progress_function, interval=node_interval)
# Cython build environment
py_include = sysconfig.get_paths()['include']
if arch == "larch64" and platform.machine() not in ("aarch64", "arm64"):
tici_py_include = tici_libpath(f"/usr/include/python{sys.version_info.major}.{sys.version_info.minor}")
if os.path.isdir(tici_py_include):
py_include = tici_py_include
envCython = env.Clone()
envCython["CPPPATH"] += [py_include, np.get_include()]
envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-shadow", "-Wno-deprecated-declarations"]
envCython["CCFLAGS"].remove("-Werror")
envCython["LIBS"] = []
if arch == "Darwin":
envCython["LINKFLAGS"] = ["-bundle", "-undefined", "dynamic_lookup"] + darwin_rpath_link_flags
else:
envCython["LINKFLAGS"] = arch_ldflags + ["-pthread", "-shared"]
np_version = SCons.Script.Value(np.__version__)
Export('envCython', 'np_version')
# Qt build environment
qt_env = env.Clone()
qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "DBus", "Xml"]
qt_libs = []
if arch == "Darwin":
qt_env['QTDIR'] = f"{brew_prefix}/opt/qt@5"
qt_dirs = [
os.path.join(qt_env['QTDIR'], "include"),
]
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:
if arch == "larch64":
qt_env.PrependENVPath('PATH', Dir("#third_party/qt5/larch64/bin/").abspath)
# For laptop/device builds that mount an AGNOS sysroot, always prefer Qt
# headers from that sysroot to keep headers/libs ABI-matched (Qt 5.12.x).
if arch == "larch64" and os.environ.get("SP_TICI_SYSROOT"):
qt_install_prefix = tici_libpath("/usr")
qt_install_headers = tici_libpath("/usr/include/aarch64-linux-gnu/qt5")
else:
qmake = os.environ.get("SP_QMAKE", "qmake")
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
qt_dirs = [
f"{qt_install_headers}",
]
qt_gui_path = os.path.join(qt_install_headers, "QtGui")
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"]
elif arch != "Darwin":
qt_libs += ["GL"]
qt_env['QT3DIR'] = qt_env['QTDIR']
qt_env.Tool('qt3')
if arch == "larch64" and os.environ.get("SP_TICI_SYSROOT"):
qt_tool_bin = tici_libpath("/usr/lib/qt5/bin")
qt_tool_root = tici_libpath("/")
qt_arm_moc = os.path.join(qt_tool_bin, "moc")
qt_arm_uic = os.path.join(qt_tool_bin, "uic")
qt_arm_rcc = os.path.join(qt_tool_bin, "rcc")
if platform.machine() in ("aarch64", "arm64"):
if os.path.isfile(qt_arm_moc):
qt_env['QT3_MOC'] = qt_arm_moc
if os.path.isfile(qt_arm_uic):
qt_env['QT3_UIC'] = qt_arm_uic
if os.path.isfile(qt_arm_rcc):
qt_env['SP_QT_RCC'] = qt_arm_rcc
else:
qt_qemu = shutil.which("qemu-aarch64-static") or shutil.which("qemu-aarch64")
if qt_qemu and os.path.isfile(qt_arm_moc):
qt_env['QT3_MOC'] = f"{qt_qemu} -L {qt_tool_root} {qt_arm_moc}"
else:
qt_host_bin = os.environ.get("SP_QT_HOST_BIN", "/usr/lib/qt5/bin")
qt_env['QT3_MOC'] = os.environ.get("SP_QT_HOST_MOC", os.path.join(qt_host_bin, "moc"))
if qt_qemu and os.path.isfile(qt_arm_uic):
qt_env['QT3_UIC'] = f"{qt_qemu} -L {qt_tool_root} {qt_arm_uic}"
else:
qt_host_bin = os.environ.get("SP_QT_HOST_BIN", "/usr/lib/qt5/bin")
qt_env['QT3_UIC'] = os.environ.get("SP_QT_HOST_UIC", os.path.join(qt_host_bin, "uic"))
if qt_qemu and os.path.isfile(qt_arm_rcc):
qt_env['SP_QT_RCC'] = f"{qt_qemu} -L {qt_tool_root} {qt_arm_rcc}"
else:
qt_env['SP_QT_RCC'] = os.environ.get("SP_QT_HOST_RCC", "rcc")
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', ]
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
SConscript(['common/SConscript'])
Import('_common', '_gpucommon')
common = [_common, 'json11', 'zmq']
gpucommon = [_gpucommon]
Export('common', 'gpucommon')
# Build messaging (cereal + msgq + socketmaster + their dependencies)
# Enable swaglog include in submodules
env_swaglog = env.Clone()
env_swaglog['CXXFLAGS'].append('-DSWAGLOG="\\"common/swaglog.h\\""')
SConscript(['msgq_repo/SConscript'], exports={'env': env_swaglog})
SConscript(['opendbc_repo/SConscript'], exports={'env': env_swaglog})
SConscript(['cereal/SConscript'])
Import('socketmaster', 'msgq')
messaging = [socketmaster, msgq, 'capnp', 'kj',]
Export('messaging')
# Build other submodules
SConscript(['panda/SConscript'])
# Build rednose library
SConscript(['rednose/SConscript'])
# Build system services
SConscript([
'system/ubloxd/SConscript',
'system/loggerd/SConscript',
])
if arch == "larch64":
SConscript(['system/camerad/SConscript'])
# Build openpilot
SConscript(['third_party/SConscript'])
SConscript(['selfdrive/SConscript'])
if Dir('#tools/cabana/').exists() and GetOption('extras'):
SConscript(['tools/replay/SConscript'])
if arch != "larch64":
SConscript(['tools/cabana/SConscript'])
external_sconscript = GetOption('external_sconscript')
if external_sconscript:
SConscript([external_sconscript])
-2972
View File
File diff suppressed because it is too large Load Diff
-6
View File
@@ -1,6 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
exec "${ROOT_DIR}/scripts/laptop_device_build.sh" build "$@"
-6
View File
@@ -1,6 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
exec "${ROOT_DIR}/scripts/host_tool_runner.sh" c3 "$@"
-6
View File
@@ -1,6 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
exec "${ROOT_DIR}/scripts/host_tool_runner.sh" c4 "$@"
-20
View File
@@ -1,20 +0,0 @@
Import('env', 'common', 'msgq')
cereal_dir = Dir('.')
gen_dir = Dir('gen')
# Build cereal
schema_files = ['log.capnp', 'car.capnp', 'legacy.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],
schema_files,
f"capnpc --src-prefix={cereal_dir.path} $SOURCES -o c++:{gen_dir.path}/cpp/")
cereal = env.Library('cereal', [f'gen/cpp/{s}.c++' for s in schema_files])
# Build messaging
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'])
socketmaster = env.Library('socketmaster', ['messaging/socketmaster.cc'])
Export('cereal', 'socketmaster')
+417 -322
View File
@@ -1,8 +1,6 @@
using Cxx = import "./include/c++.capnp"; using Cxx = import "./include/c++.capnp";
$Cxx.namespace("cereal"); $Cxx.namespace("cereal");
using Car = import "car.capnp";
@0xb526ba661d550a59; @0xb526ba661d550a59;
# custom.capnp: a home for empty structs reserved for custom forks # custom.capnp: a home for empty structs reserved for custom forks
@@ -12,189 +10,43 @@ using Car = import "car.capnp";
# DO rename the structs # DO rename the structs
# DON'T change the identifier (e.g. @0x81c2f05a394cf4af) # DON'T change the identifier (e.g. @0x81c2f05a394cf4af)
struct StarPilotCarControl @0x81c2f05a394cf4af { struct ModularAssistiveDrivingSystem {
hudControl @0 :HUDControl; state @0 :ModularAssistiveDrivingSystemState;
enabled @1 :Bool;
active @2 :Bool;
available @3 :Bool;
struct HUDControl { enum ModularAssistiveDrivingSystemState {
audibleAlert @0 :AudibleAlert; disabled @0;
paused @1;
enabled @2;
softDisabling @3;
overriding @4;
}
}
enum AudibleAlert { 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; none @0;
increase @1;
engage @1; decrease @2;
disengage @2;
refuse @3;
warningSoft @4;
warningImmediate @5;
prompt @6;
promptRepeat @7;
promptDistracted @8;
# Random Events
angry @9;
continued @10;
dejaVu @11;
doc @12;
fart @13;
firefox @14;
goat @15;
hal9000 @16;
mail @17;
nessie @18;
noice @19;
startup @20;
thisIsFine @21;
uwu @22;
}
} }
} }
struct StarPilotCarParams @0xaedffd8f31e7b55d { # Same struct as Log.RadarState.LeadData
alternativeExperience @0 :Int16; struct LeadData {
canUsePedal @1 :Bool;
canUseSDSU @2 :Bool;
flags @3 :UInt32;
isHDA2 @4 :Bool;
openpilotLongitudinalControlDisabled @5 :Bool;
safetyConfigs @6 :List(SafetyConfig);
struct SafetyConfig {
safetyParam @0 :UInt16;
}
}
struct StarPilotCarState @0xf35cc4560bbf6ec2 {
accelPressed @0 :Bool;
alwaysOnLateralEnabled @1 :Bool;
brakeLights @2 :Bool;
dashboardSpeedLimit @3 :Float32;
decelPressed @4 :Bool;
distancePressed @5 :Bool;
distanceLongPressed @6 :Bool;
distanceVeryLongPressed @7 :Bool;
ecoGear @8 :Bool;
forceCoast @9 :Bool;
isParked @10 :Bool;
pauseLateral @11 :Bool;
pauseLongitudinal @12 :Bool;
sportGear @13 :Bool;
trafficModeEnabled @14 :Bool;
gasStack @15 :Bool; # Compatibility with older StarPilot payloads
}
struct StarPilotDeviceState @0xda96579883444c35 {
freeSpace @0 :Int16;
usedSpace @1 :Int16;
}
struct StarPilotModelDataV2 @0x80ae746ee2596b11 {
turnDirection @0 :TurnDirection;
enum TurnDirection {
none @0;
turnLeft @1;
turnRight @2;
}
}
struct StarPilotOnroadEvent @0xa5cd762cd951a455 {
name @0 :EventName;
enable @1 :Bool;
noEntry @2 :Bool;
warning @3 :Bool;
userDisable @4 :Bool;
softDisable @5 :Bool;
immediateDisable @6 :Bool;
preEnable @7 :Bool;
permanent @8 :Bool;
overrideLateral @9 :Bool;
overrideLongitudinal @10 :Bool;
enum EventName {
blockUser @0;
customStartupAlert @1;
forcingStop @2;
goatSteerSaturated @3;
greenLight @4;
holidayActive @5;
laneChangeBlockedLoud @6;
leadDeparting @7;
noLaneAvailable @8;
nnffLoaded @9;
openpilotCrashed @10;
pedalInterceptorNoBrake @11;
speedLimitChanged @12;
trafficModeActive @13;
trafficModeInactive @14;
turningLeft @15;
turningRight @16;
# Random Events
accel30 @17;
accel35 @18;
accel40 @19;
dejaVuCurve @20;
firefoxSteerSaturated @21;
hal9000 @22;
openpilotCrashedRandomEvent @23;
thisIsFineSteerSaturated @24;
toBeContinued @25;
vCruise69 @26;
yourFrogTriedToKillMe @27;
youveGotMail @28;
switchbackModeActive @29;
switchbackModeInactive @30;
}
}
struct StarPilotPlan @0xf98d843bfd7004a3 {
accelerationJerk @0 :Float32;
cscControllingSpeed @1 :Bool;
cscSpeed @2 :Float32;
cscTraining @3 :Bool;
dangerFactor @4 :Float32;
dangerJerk @5 :Float32;
desiredFollowDistance @6 :Int64;
experimentalMode @7 :Bool;
forcingStop @8 :Bool;
forcingStopLength @9 :Float32;
starpilotEvents @10 :List(StarPilotOnroadEvent);
starpilotToggles @11 :Text;
increasedStoppedDistance @12 :Float32;
lateralCheck @13 :Bool;
laneWidthLeft @14 :Float32;
laneWidthRight @15 :Float32;
maxAcceleration @16 :Float32;
minAcceleration @17 :Float32;
redLight @18 :Bool;
roadCurvature @19 :Float32;
slcMapSpeedLimit @20 :Float32;
slcMapboxSpeedLimit @21 :Float32;
slcNextSpeedLimit @22 :Float32;
slcOverriddenSpeed @23 :Float32;
slcSpeedLimit @24 :Float32;
slcSpeedLimitOffset @25 :Float32;
slcSpeedLimitSource @26 :Text;
speedJerk @27 :Float32;
speedLimitChanged @28 :Bool;
tFollow @29 :Float32;
themeUpdated @30 :Bool;
unconfirmedSlcSpeedLimit @31 :Float32;
vCruise @32 :Float32;
weatherDaytime @33 :Bool;
weatherId @34 :Int16;
disableThrottle @35 :Bool;
trackingLead @36 :Bool;
}
struct StarPilotRadarState @0xb86e6369214c01c8 {
leadLeft @0 :LeadData;
leadRight @1 :LeadData;
struct LeadData {
dRel @0 :Float32; dRel @0 :Float32;
yRel @1 :Float32; yRel @1 :Float32;
vRel @2 :Float32; vRel @2 :Float32;
@@ -212,39 +64,396 @@ struct StarPilotRadarState @0xb86e6369214c01c8 {
radarTrackId @15 :Int32 = -1; radarTrackId @15 :Int32 = -1;
aLeadDEPRECATED @5 :Float32; aLeadDEPRECATED @5 :Float32;
}
} }
struct StarPilotSelfdriveState @0xf416ec09499d9d19 { struct SelfdriveStateSP @0x81c2f05a394cf4af {
alertText1 @0 :Text; mads @0 :ModularAssistiveDrivingSystem;
alertText2 @1 :Text; intelligentCruiseButtonManagement @1 :IntelligentCruiseButtonManagement;
alertStatus @2 :AlertStatus;
alertSize @3 :AlertSize;
alertType @4 :Text;
alertSound @5 :Car.CarControl.HUDControl.AudibleAlert;
enum AlertStatus { enum AudibleAlert {
normal @0;
userPrompt @1;
critical @2;
starpilot @3;
}
enum AlertSize {
none @0; none @0;
small @1;
mid @2; engage @1;
full @3; 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 CustomReserved9 @0xa1680744031fdb2d { struct ModelManagerSP @0xaedffd8f31e7b55d {
slotId @0 :Text; activeBundle @0 :ModelBundle;
slotName @1 :Text; selectedBundle @1 :ModelBundle;
variant @2 :Text; availableBundles @2 :List(ModelBundle);
variantLabel @3 :Text;
reason @4 :Text; struct DownloadUri {
wallTimeNanos @5 :UInt64; 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 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 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 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 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 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 {
@@ -268,125 +477,11 @@ struct CustomReserved15 @0xbd443b539493bc68 {
struct CustomReserved16 @0xfc6241ed8877b611 { struct CustomReserved16 @0xfc6241ed8877b611 {
} }
struct MapdDownloadLocationDetails @0xff889853e7b0987f { struct CustomReserved17 @0xa30662f84033036c {
location @0 :Text;
totalFiles @1 :UInt32;
downloadedFiles @2 :UInt32;
} }
struct MapdDownloadProgress @0xfaa35dcac85073a2 { struct CustomReserved18 @0xc86a3d38d13eb3ef {
active @0 :Bool;
cancelled @1 :Bool;
totalFiles @2 :UInt32;
downloadedFiles @3 :UInt32;
locations @4 :List(Text);
locationDetails @5 :List(MapdDownloadLocationDetails);
} }
struct MapdPathPoint @0xd6f78acca1bc3939 { struct CustomReserved19 @0xa4f1eb3323f5f582 {
latitude @0 :Float64;
longitude @1 :Float64;
curvature @2 :Float32;
targetVelocity @3 :Float32;
}
struct MapdExtendedOut @0xa30662f84033036c {
downloadProgress @0 :MapdDownloadProgress;
settings @1 :Text;
path @2 :List(MapdPathPoint);
}
enum MapdInputType {
download @0;
setTargetLateralAccel @1;
setSpeedLimitOffset @2;
setSpeedLimitControl @3;
setMapCurveSpeedControl @4;
setVisionCurveSpeedControl @5;
setLogLevel @6;
setVisionCurveTargetLatA @7;
setVisionCurveMinTargetV @8;
reloadSettings @9;
saveSettings @10;
setEnableSpeed @11;
setVisionCurveUseEnableSpeed @12;
setMapCurveUseEnableSpeed @13;
setSpeedLimitUseEnableSpeed @14;
setHoldLastSeenSpeedLimit @15;
setTargetSpeedJerk @16;
setTargetSpeedAccel @17;
setTargetSpeedTimeOffset @18;
setDefaultLaneWidth @19;
setMapCurveTargetLatA @20;
loadDefaultSettings @21;
loadRecommendedSettings @22;
setSlowDownForNextSpeedLimit @23;
setSpeedUpForNextSpeedLimit @24;
setHoldSpeedLimitWhileChangingSetSpeed @25;
loadPersistentSettings @26;
cancelDownload @27;
setLogJson @28;
setLogSource @29;
setExternalSpeedLimitControl @30;
setExternalSpeedLimit @31;
setSpeedLimitPriority @32;
setSpeedLimitChangeRequiresAccept @33;
acceptSpeedLimit @34;
setPressGasToAcceptSpeedLimit @35;
setAdjustSetSpeedToAcceptSpeedLimit @36;
setAcceptSpeedLimitTimeout @37;
setPressGasToOverrideSpeedLimit @38;
}
enum WaySelectionType {
current @0;
predicted @1;
possible @2;
extended @3;
fail @4;
}
enum SpeedLimitOffsetType {
static @0;
percent @1;
}
struct MapdIn @0xc86a3d38d13eb3ef {
type @0 :MapdInputType;
float @1 :Float32;
str @2 :Text;
bool @3 :Bool;
}
enum RoadContext {
freeway @0;
city @1;
unknown @2;
}
struct MapdOut @0xa4f1eb3323f5f582 {
wayName @0 :Text;
wayRef @1 :Text;
roadName @2 :Text;
speedLimit @3 :Float32;
nextSpeedLimit @4 :Float32;
nextSpeedLimitDistance @5 :Float32;
hazard @6 :Text;
nextHazard @7 :Text;
nextHazardDistance @8 :Float32;
advisorySpeed @9 :Float32;
nextAdvisorySpeed @10 :Float32;
nextAdvisorySpeedDistance @11 :Float32;
oneWay @12 :Bool;
lanes @13 :UInt8;
tileLoaded @14 :Bool;
speedLimitSuggestedSpeed @15 :Float32;
suggestedSpeed @16 :Float32;
estimatedRoadWidth @17 :Float32;
roadContext @18 :RoadContext;
distanceFromWayCenter @19 :Float32;
visionCurveSpeed @20 :Float32;
mapCurveSpeed @21 :Float32;
waySelectionType @22 :WaySelectionType;
speedLimitAccepted @23 :Bool;
} }
+789
View File
@@ -0,0 +1,789 @@
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 LateralCurvatureState @0xad9d8095c06f7c61 {
active @0 :Bool;
actualCurvature @1 :Float32;
desiredCurvature @2 :Float32;
error @3 :Float32;
p @4 :Float32;
i @5 :Float32;
f @6 :Float32;
output @7 :Float32;
saturated @8 :Bool;
}
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);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-574
View File
@@ -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;
}
Binary file not shown.
Binary file not shown.
+326 -474
View File
File diff suppressed because it is too large Load Diff
+3 -28
View File
@@ -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, \
Context, Poller, SubSocket, PubSocket, SocketEventHandle, toggle_fake_events, \
set_fake_prefix, get_fake_prefix, delete_fake_prefix, wait_for_one_event set_fake_prefix, get_fake_prefix, delete_fake_prefix, wait_for_one_event
from msgq.ipc_pyx import MultiplePublishersError, IpcError
from msgq import fake_event_handle, drain_sock_raw
import msgq import msgq
import os import os
import capnp import capnp
import time import time
@@ -13,7 +11,7 @@ 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
@@ -197,10 +195,6 @@ class SubMaster:
self.data[s] = getattr(data.as_reader(), s) self.data[s] = getattr(data.as_reader(), s)
self.freq_tracker[s] = FrequencyTracker(SERVICE_LIST[s].frequency, self.update_freq, s == poll) self.freq_tracker[s] = FrequencyTracker(SERVICE_LIST[s].frequency, self.update_freq, s == poll)
# StarPilot variables
self.addr = addr
self.poll = poll
def __getitem__(self, s: str) -> capnp.lib.capnp._DynamicStructReader: def __getitem__(self, s: str) -> capnp.lib.capnp._DynamicStructReader:
return self.data[s] return self.data[s]
@@ -252,18 +246,6 @@ class SubMaster:
def all_checks(self, service_list: Optional[List[str]] = None) -> bool: def all_checks(self, service_list: Optional[List[str]] = None) -> bool:
return self.all_alive(service_list) and self.all_freq_ok(service_list) and self.all_valid(service_list) return self.all_alive(service_list) and self.all_freq_ok(service_list) and self.all_valid(service_list)
# StarPilot variables
def extend(self, new_services: List[str]):
return SubMaster(
self.services + new_services,
poll=self.poll,
ignore_alive=self.ignore_alive,
ignore_avg_freq=self.ignore_average_freq,
ignore_valid=self.ignore_valid,
addr=self.addr,
frequency=None if self.poll is not None else self.update_freq,
)
class PubMaster: class PubMaster:
def __init__(self, services: List[str]): def __init__(self, services: List[str]):
@@ -285,10 +267,3 @@ class PubMaster:
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() # type: ignore
# StarPilot variables
def extend(self, new_services: List[str]):
for service in new_services:
if service not in self.sock:
self.sock[service] = pub_sock(service)
return self
Binary file not shown.
+8 -7
View File
@@ -25,15 +25,16 @@ void msgq_to_zmq(const std::vector<std::string> &endpoints, const std::string &i
} }
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);
+170
View File
@@ -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;
}
+72
View File
@@ -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;
};
+9 -7
View File
@@ -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();
+5 -6
View File
@@ -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;
}; };
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+251
View File
@@ -0,0 +1,251 @@
#!/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 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 dump_schema(path: str) -> None:
from cereal import log
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(peer_path: str) -> int:
from cereal import log
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)")
args = parser.parse_args()
try:
if args.generate:
dump_schema(args.file)
return 0
return run_read(args.file)
except ImportError as exc:
print(f"error: cannot import cereal ({exc}). did scons build cereal?")
return 2
if __name__ == "__main__":
sys.exit(main())
+13 -15
View File
@@ -22,8 +22,8 @@ static std::map<std::string, service> services = {
{ "roadEncodeIdx", {"roadEncodeIdx", false, 20.000000, 1, 256000}}, { "roadEncodeIdx", {"roadEncodeIdx", false, 20.000000, 1, 256000}},
{ "liveTracks", {"liveTracks", true, 20.000000, -1, 256000}}, { "liveTracks", {"liveTracks", true, 20.000000, -1, 256000}},
{ "sendcan", {"sendcan", true, 100.000000, 139, 2097152}}, { "sendcan", {"sendcan", true, 100.000000, 139, 2097152}},
{ "logMessage", {"logMessage", true, 0.000000, -1, 256000}}, { "logMessage", {"logMessage", true, 0.000000, -1, 10485760}},
{ "errorLogMessage", {"errorLogMessage", true, 0.000000, 1, 256000}}, { "errorLogMessage", {"errorLogMessage", true, 0.000000, 1, 10485760}},
{ "liveCalibration", {"liveCalibration", true, 4.000000, 4, 256000}}, { "liveCalibration", {"liveCalibration", true, 4.000000, 4, 256000}},
{ "liveTorqueParameters", {"liveTorqueParameters", true, 4.000000, 1, 256000}}, { "liveTorqueParameters", {"liveTorqueParameters", true, 4.000000, 1, 256000}},
{ "liveDelay", {"liveDelay", true, 4.000000, 1, 256000}}, { "liveDelay", {"liveDelay", true, 4.000000, 1, 256000}},
@@ -72,6 +72,17 @@ static std::map<std::string, service> services = {
{ "driverEncodeData", {"driverEncodeData", false, 20.000000, -1, 10485760}}, { "driverEncodeData", {"driverEncodeData", false, 20.000000, -1, 10485760}},
{ "wideRoadEncodeData", {"wideRoadEncodeData", false, 20.000000, -1, 10485760}}, { "wideRoadEncodeData", {"wideRoadEncodeData", false, 20.000000, -1, 10485760}},
{ "qRoadEncodeData", {"qRoadEncodeData", false, 20.000000, -1, 10485760}}, { "qRoadEncodeData", {"qRoadEncodeData", false, 20.000000, -1, 10485760}},
{ "modelManagerSP", {"modelManagerSP", false, 1.000000, 1, 10485760}},
{ "backupManagerSP", {"backupManagerSP", false, 1.000000, 1, 10485760}},
{ "selfdriveStateSP", {"selfdriveStateSP", true, 100.000000, 10, 256000}},
{ "longitudinalPlanSP", {"longitudinalPlanSP", true, 20.000000, 10, 256000}},
{ "onroadEventsSP", {"onroadEventsSP", true, 1.000000, 1, 256000}},
{ "carParamsSP", {"carParamsSP", true, 0.020000, 1, 256000}},
{ "carControlSP", {"carControlSP", true, 100.000000, 10, 256000}},
{ "carStateSP", {"carStateSP", true, 100.000000, 10, 256000}},
{ "liveMapDataSP", {"liveMapDataSP", true, 1.000000, 1, 256000}},
{ "modelDataV2SP", {"modelDataV2SP", true, 20.000000, -1, 10485760}},
{ "liveLocationKalman", {"liveLocationKalman", true, 20.000000, -1, 256000}},
{ "uiDebug", {"uiDebug", true, 0.000000, 1, 256000}}, { "uiDebug", {"uiDebug", true, 0.000000, 1, 256000}},
{ "testJoystick", {"testJoystick", true, 0.000000, -1, 256000}}, { "testJoystick", {"testJoystick", true, 0.000000, -1, 256000}},
{ "alertDebug", {"alertDebug", true, 20.000000, 5, 256000}}, { "alertDebug", {"alertDebug", true, 20.000000, 5, 256000}},
@@ -81,22 +92,9 @@ static std::map<std::string, service> services = {
{ "livestreamWideRoadEncodeData", {"livestreamWideRoadEncodeData", false, 20.000000, -1, 2097152}}, { "livestreamWideRoadEncodeData", {"livestreamWideRoadEncodeData", false, 20.000000, -1, 2097152}},
{ "livestreamRoadEncodeData", {"livestreamRoadEncodeData", false, 20.000000, -1, 2097152}}, { "livestreamRoadEncodeData", {"livestreamRoadEncodeData", false, 20.000000, -1, 2097152}},
{ "livestreamDriverEncodeData", {"livestreamDriverEncodeData", false, 20.000000, -1, 2097152}}, { "livestreamDriverEncodeData", {"livestreamDriverEncodeData", false, 20.000000, -1, 2097152}},
{ "customReserved9", {"customReserved9", true, 0.000000, 1, 256000}},
{ "customReservedRawData0", {"customReservedRawData0", true, 0.000000, -1, 256000}}, { "customReservedRawData0", {"customReservedRawData0", true, 0.000000, -1, 256000}},
{ "customReservedRawData1", {"customReservedRawData1", true, 0.000000, -1, 256000}}, { "customReservedRawData1", {"customReservedRawData1", true, 0.000000, -1, 256000}},
{ "customReservedRawData2", {"customReservedRawData2", true, 0.000000, -1, 256000}}, { "customReservedRawData2", {"customReservedRawData2", true, 0.000000, -1, 256000}},
{ "starpilotCarControl", {"starpilotCarControl", true, 100.000000, 10, 256000}},
{ "starpilotCarParams", {"starpilotCarParams", true, 0.020000, 1, 256000}},
{ "starpilotCarState", {"starpilotCarState", true, 100.000000, 10, 256000}},
{ "starpilotDeviceState", {"starpilotDeviceState", true, 2.000000, 1, 256000}},
{ "starpilotModelV2", {"starpilotModelV2", true, 20.000000, -1, 256000}},
{ "starpilotOnroadEvents", {"starpilotOnroadEvents", true, 1.000000, 1, 256000}},
{ "starpilotPlan", {"starpilotPlan", true, 20.000000, 10, 256000}},
{ "starpilotRadarState", {"starpilotRadarState", true, 20.000000, 5, 256000}},
{ "starpilotSelfdriveState", {"starpilotSelfdriveState", true, 100.000000, 10, 256000}},
{ "mapdExtendedOut", {"mapdExtendedOut", true, 1.000000, 1, 2097152}},
{ "mapdIn", {"mapdIn", true, 1.000000, 1, 2097152}},
{ "mapdOut", {"mapdOut", true, 20.000000, 20, 2097152}},
}; };
#endif #endif
+15 -17
View File
@@ -39,8 +39,8 @@ _services: dict[str, tuple] = {
"roadEncodeIdx": (False, 20., 1), "roadEncodeIdx": (False, 20., 1),
"liveTracks": (True, 20.), "liveTracks": (True, 20.),
"sendcan": (True, 100., 139, QueueSize.MEDIUM), "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),
@@ -90,6 +90,19 @@ _services: dict[str, tuple] = {
"wideRoadEncodeData": (False, 20., None, QueueSize.BIG), "wideRoadEncodeData": (False, 20., None, QueueSize.BIG),
"qRoadEncodeData": (False, 20., None, QueueSize.BIG), "qRoadEncodeData": (False, 20., None, QueueSize.BIG),
# sunnypilot
"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.),
# debug # debug
"uiDebug": (True, 0., 1), "uiDebug": (True, 0., 1),
"testJoystick": (True, 0.), "testJoystick": (True, 0.),
@@ -100,24 +113,9 @@ _services: dict[str, tuple] = {
"livestreamWideRoadEncodeData": (False, 20., None, QueueSize.MEDIUM), "livestreamWideRoadEncodeData": (False, 20., None, QueueSize.MEDIUM),
"livestreamRoadEncodeData": (False, 20., None, QueueSize.MEDIUM), "livestreamRoadEncodeData": (False, 20., None, QueueSize.MEDIUM),
"livestreamDriverEncodeData": (False, 20., None, QueueSize.MEDIUM), "livestreamDriverEncodeData": (False, 20., None, QueueSize.MEDIUM),
"customReserved9": (True, 0., 1),
"customReservedRawData0": (True, 0.), "customReservedRawData0": (True, 0.),
"customReservedRawData1": (True, 0.), "customReservedRawData1": (True, 0.),
"customReservedRawData2": (True, 0.), "customReservedRawData2": (True, 0.),
# StarPilot variables
"starpilotCarControl": (True, 100., 10),
"starpilotCarParams": (True, 0.02, 1),
"starpilotCarState": (True, 100., 10),
"starpilotDeviceState": (True, 2., 1),
"starpilotModelV2": (True, 20.),
"starpilotOnroadEvents": (True, 1., 1),
"starpilotPlan": (True, 20., 10),
"starpilotRadarState": (True, 20., 5),
"starpilotSelfdriveState": (True, 100., 10),
"mapdExtendedOut": (True, 1., 1, QueueSize.MEDIUM),
"mapdIn": (True, 1., 1, QueueSize.MEDIUM),
"mapdOut": (True, 20., 20, QueueSize.MEDIUM),
} }
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())}
-2
View File
@@ -1,2 +0,0 @@
*.cpp
!params_pyx.cpp
-35
View File
@@ -1,35 +0,0 @@
Import('env', 'envCython', 'arch')
common_libs = [
'params.cc',
'swaglog.cc',
'util.cc',
'watchdog.cc',
'ratekeeper.cc'
]
_common = env.Library('common', common_libs, LIBS="json11")
files = [
'clutil.cc',
]
_gpucommon = env.Library('gpucommon', files)
Export('_common', '_gpucommon')
if GetOption('extras'):
env.Program('tests/test_common',
['tests/test_runner.cc', 'tests/test_params.cc', 'tests/test_util.cc', 'tests/test_swaglog.cc'],
LIBS=[_common, 'json11', 'zmq', 'pthread'])
# Cython bindings
params_python = envCython.Program('params_pyx.so', 'params_pyx.pyx', LIBS=envCython['LIBS'] + [_common, 'zmq', 'json11'])
SConscript([
'transformations/SConscript',
])
Import('transformations_python')
common_python = [params_python, transformations_python]
Export('common_python')
-64
View File
@@ -1,64 +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
from openpilot.starpilot.common.starpilot_utilities import use_konik_server
API_HOST = os.getenv('API_HOST', f"https://api.{'konik.ai' if use_konik_server() else 'commadotai.com'}")
# name: jwt signature algorithm
KEYS = {"id_rsa": "RS256",
"id_ecdsa": "ES256"}
class Api:
def __init__(self, dongle_id):
self.dongle_id = dongle_id
self.jwt_algorithm, self.private_key, _ = 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 api_get(endpoint, method=method, timeout=timeout, access_token=access_token, **params)
def get_token(self, payload_extra=None, 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)
}
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 api_get(endpoint, method='GET', timeout=None, access_token=None, session=None, **params):
headers = {}
if access_token is not None:
headers['Authorization'] = "JWT " + access_token
headers['User-Agent'] = "openpilot-" + get_version()
# TODO: add session to Api
req = requests if session is None else session
return req.request(method, API_HOST + "/" + endpoint, timeout=timeout, headers=headers, params=params)
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
+26
View File
@@ -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()
+72
View File
@@ -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
+11
View File
@@ -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-"
-129
View File
@@ -1,129 +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());
}
std::string resolve_program_path(const char *path) {
std::string resolved_path(path);
if (util::file_exists(resolved_path)) {
return resolved_path;
}
const std::string basedir = util::getenv("BASEDIR", "");
if (!basedir.empty()) {
// Handle repository-relative paths, e.g. "selfdrive/modeld/transforms/transform.cl".
if (!resolved_path.empty() && resolved_path.front() != '/') {
const std::string candidate = basedir + "/" + resolved_path;
if (util::file_exists(candidate)) {
return candidate;
}
}
// Recover from build-path-embedded absolute paths like "/work/selfdrive/...".
for (const char *marker : {"/selfdrive/", "/starpilot/", "/common/"}) {
if (const size_t idx = resolved_path.find(marker); idx != std::string::npos) {
const std::string candidate = basedir + "/" + resolved_path.substr(idx + 1);
if (util::file_exists(candidate)) {
LOGW("OpenCL source path remapped: %s -> %s", resolved_path.c_str(), candidate.c_str());
return candidate;
}
}
}
}
return resolved_path;
}
} // 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(resolve_program_path(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;
}
-28
View File
@@ -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);
-6
View File
@@ -19,11 +19,5 @@ class CV:
# Mass # Mass
LB_TO_KG = 0.453592 LB_TO_KG = 0.453592
# StarPilot variables
METER_TO_FOOT = 3.28084
FOOT_TO_METER = 1. / METER_TO_FOOT
CM_TO_INCH = 1. / 2.54
INCH_TO_CM = 1. / CM_TO_INCH
ACCELERATION_DUE_TO_GRAVITY = 9.81 # m/s^2 ACCELERATION_DUE_TO_GRAVITY = 9.81 # m/s^2
+1 -5
View File
@@ -4,20 +4,16 @@ from pathlib import Path
CHUNK_SIZE = 45 * 1024 * 1024 # 45MB, under GitHub's 50MB limit CHUNK_SIZE = 45 * 1024 * 1024 # 45MB, under GitHub's 50MB limit
def get_chunk_name(name, idx, num_chunks): def get_chunk_name(name, idx, num_chunks):
return f"{name}.chunk{idx + 1:02d}of{num_chunks:02d}" return f"{name}.chunk{idx+1:02d}of{num_chunks:02d}"
def get_manifest_path(name): def get_manifest_path(name):
return f"{name}.chunkmanifest" return f"{name}.chunkmanifest"
def get_chunk_paths(path, file_size): def get_chunk_paths(path, file_size):
num_chunks = math.ceil(file_size / CHUNK_SIZE) num_chunks = math.ceil(file_size / CHUNK_SIZE)
return [get_manifest_path(path)] + [get_chunk_name(path, i, num_chunks) for i in range(num_chunks)] return [get_manifest_path(path)] + [get_chunk_name(path, i, num_chunks) for i in range(num_chunks)]
def chunk_file(path, targets): def chunk_file(path, targets):
manifest_path, *chunk_paths = targets manifest_path, *chunk_paths = targets
with open(path, 'rb') as f: with open(path, 'rb') as f:
+1 -1
View File
@@ -28,7 +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
+6 -6
View File
@@ -4,27 +4,27 @@ 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) \
+81
View File
@@ -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]]
Binary file not shown.
-85
View File
@@ -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));
}
+1
View File
@@ -0,0 +1 @@
#define DEFAULT_MODEL "POP model (Default)"
+47
View File
@@ -0,0 +1,47 @@
import sys
import pytest
import inspect
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):
name = f"{cls.__name__}_{i}"
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
+12 -86
View File
@@ -91,35 +91,25 @@ private:
} // namespace } // namespace
Params::Params(const std::string &path, bool memory) { Params::Params(const std::string &path) {
params_prefix = "/" + util::getenv("OPENPILOT_PREFIX", "d"); params_prefix = "/" + util::getenv("OPENPILOT_PREFIX", "d");
params_path = ensure_params_path(params_prefix, path);
// StarPilot variables
std::string params_folder;
if (memory) {
params_folder = Path::shm_path() + "/params";
} else {
cache_path = "/cache/params" + params_prefix + "/";
params_folder = path;
}
params_path = ensure_params_path(params_prefix, params_folder);
} }
Params::~Params() { Params::~Params() {
if (future.valid()) { if (future.valid()) {
future.wait(); future.wait();
} }
std::scoped_lock lk(pending_writes_lock);
assert(queue.empty()); assert(queue.empty());
assert(pending_writes.empty());
assert(!writer_running);
} }
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) {
if (flag == ALL || (p.second.flags & flag)) {
ret.push_back(p.first); ret.push_back(p.first);
} }
}
return ret; return ret;
} }
@@ -181,12 +171,6 @@ int Params::put(const char* key, const char* value, size_t value_size) {
int Params::remove(const std::string &key) { int Params::remove(const std::string &key) {
FileLock file_lock(params_path + "/.lock"); FileLock file_lock(params_path + "/.lock");
int result = unlink(getParamPath(key).c_str()); int result = unlink(getParamPath(key).c_str());
// StarPilot variables
if (!cache_path.empty()) {
unlink((cache_path + key).c_str());
}
if (result != 0) { if (result != 0) {
return result; return result;
} }
@@ -233,11 +217,6 @@ void Params::clearAll(ParamKeyFlag key_flag) {
auto it = keys.find(de->d_name); auto it = keys.find(de->d_name);
if (it == keys.end() || (it->second.flags & key_flag)) { if (it == keys.end() || (it->second.flags & key_flag)) {
unlink(getParamPath(de->d_name).c_str()); unlink(getParamPath(de->d_name).c_str());
// StarPilot variables
if (!cache_path.empty()) {
unlink((cache_path + de->d_name).c_str());
}
} }
} }
} }
@@ -248,71 +227,18 @@ void Params::clearAll(ParamKeyFlag key_flag) {
} }
void Params::putNonBlocking(const std::string &key, const std::string &val) { void Params::putNonBlocking(const std::string &key, const std::string &val) {
bool should_enqueue = false; queue.push(std::make_pair(key, val));
bool should_start_thread = false; // start thread on demand
if (!future.valid() || future.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready) {
{
std::scoped_lock lk(pending_writes_lock);
auto it = pending_writes.find(key);
if (it == pending_writes.end()) {
pending_writes.emplace(key, val);
should_enqueue = true;
} else {
it->second = val;
}
if (!writer_running) {
writer_running = true;
should_start_thread = true;
}
}
if (should_enqueue) {
queue.push(key);
}
if (should_start_thread) {
future = std::async(std::launch::async, &Params::asyncWriteThread, this); future = std::async(std::launch::async, &Params::asyncWriteThread, this);
} }
} }
void Params::asyncWriteThread() { void Params::asyncWriteThread() {
std::string key; // TODO: write the latest one if a key has multiple values in the queue.
while (true) { std::pair<std::string, std::string> p;
if (!queue.try_pop(key, 0)) { while (queue.try_pop(p, 0)) {
std::scoped_lock lk(pending_writes_lock);
if (queue.empty() && pending_writes.empty()) {
writer_running = false;
return;
}
continue;
}
std::string val;
{
std::scoped_lock lk(pending_writes_lock);
auto it = pending_writes.find(key);
if (it == pending_writes.end()) {
continue;
}
val = std::move(it->second);
pending_writes.erase(it);
}
// Params::put is Thread-Safe // Params::put is Thread-Safe
put(key, val); put(p.first, p.second);
} }
} }
// StarPilot variables
int Params::getTuningLevel(const std::string &key) {
return keys[key].tuning_level;
}
std::optional<std::string> Params::getStockValue(const std::string &key) {
ParamKeyAttributes &attributes = keys[key];
if (attributes.stock_value) {
return attributes.stock_value;
}
return attributes.default_value;
}
+4 -45
View File
@@ -2,11 +2,9 @@
#include <future> #include <future>
#include <map> #include <map>
#include <mutex>
#include <optional> #include <optional>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <unordered_map>
#include <utility> #include <utility>
#include <vector> #include <vector>
@@ -20,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
}; };
@@ -37,22 +36,17 @@ struct ParamKeyAttributes {
uint32_t flags; uint32_t flags;
ParamKeyType type; ParamKeyType type;
std::optional<std::string> default_value = std::nullopt; std::optional<std::string> default_value = std::nullopt;
// StarPilot variables
std::optional<std::string> stock_value = std::nullopt;
int tuning_level = 0;
}; };
class Params { class Params {
public: public:
explicit Params(const std::string &path = {}, bool memory = false); explicit Params(const std::string &path = {});
~Params(); ~Params();
// Not copyable. // Not copyable.
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);
@@ -85,35 +79,6 @@ public:
putNonBlocking(key, val ? "1" : "0"); putNonBlocking(key, val ? "1" : "0");
} }
// StarPilot variables
int getInt(const std::string &key, bool block = false) {
std::string value = get(key, block);
return value.empty() ? 0 : std::stoi(value);
}
float getFloat(const std::string &key, bool block = false) {
std::string value = get(key, block);
return value.empty() ? 0.0f : std::stof(value);
}
int putInt(const std::string &key, int val) {
std::string str = std::to_string(val);
return put(key.c_str(), str.c_str(), str.size());
}
int putFloat(const std::string &key, float val) {
std::string str = std::to_string(val);
return put(key.c_str(), str.c_str(), str.size());
}
void putIntNonBlocking(const std::string &key, int val) {
putNonBlocking(key, std::to_string(val));
}
void putFloatNonBlocking(const std::string &key, float val) {
putNonBlocking(key, std::to_string(val));
}
int getTuningLevel(const std::string &key);
std::optional<std::string> getStockValue(const std::string &key);
private: private:
void asyncWriteThread(); void asyncWriteThread();
@@ -122,11 +87,5 @@ private:
// for nonblocking write // for nonblocking write
std::future<void> future; std::future<void> future;
SafeQueue<std::string> queue; SafeQueue<std::pair<std::string, std::string>> queue;
std::mutex pending_writes_lock;
std::unordered_map<std::string, std::string> pending_writes;
bool writer_running = false;
// StarPilot variables
std::string cache_path;
}; };
+2 -64
View File
@@ -1,71 +1,9 @@
from openpilot.common.params_pyx import Params as _Params, ParamKeyFlag, ParamKeyType, UnknownKeyName from openpilot.common.params_pyx import Params, ParamKeyFlag, ParamKeyType, UnknownKeyName
assert _Params assert Params
assert ParamKeyFlag assert ParamKeyFlag
assert ParamKeyType assert ParamKeyType
assert UnknownKeyName assert UnknownKeyName
class Params(_Params):
def get(self, key, block=False, return_default=False, encoding=None, default=None):
try:
value = super().get(key, block=block, return_default=return_default)
except UnknownKeyName:
return default
if value is None:
return default
if encoding is not None and isinstance(value, bytes):
try:
return value.decode(encoding)
except Exception:
return value.decode("utf-8", errors="replace")
return value
def get_bool(self, key, block=False, default=False):
try:
return super().get_bool(key, block=block)
except UnknownKeyName:
return bool(default)
def get_int(self, key, block=False, return_default=False, default=0):
val = self.get(key, block=block, return_default=return_default, encoding="utf-8")
if val is None or val == "":
return default
try:
return int(float(val))
except ValueError:
return default
def get_float(self, key, block=False, return_default=False, default=0.0):
val = self.get(key, block=block, return_default=return_default, encoding="utf-8")
if val is None or val == "":
return default
try:
return float(val)
except ValueError:
return default
def put_int(self, key, val):
t = self.get_type(key)
if t == ParamKeyType.FLOAT:
self.put(key, float(val))
elif t == ParamKeyType.INT:
self.put(key, int(val))
elif t == ParamKeyType.BOOL:
self.put(key, bool(val))
else:
self.put(key, str(int(val)))
def put_float(self, key, val):
t = self.get_type(key)
if t == ParamKeyType.FLOAT:
self.put(key, float(val))
elif t == ParamKeyType.INT:
self.put(key, int(val))
elif t == ParamKeyType.BOOL:
self.put(key, bool(val))
else:
self.put(key, str(float(val)))
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
+170 -450
View File
@@ -7,9 +7,8 @@
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}},
{"AlwaysAllowUploads", {PERSISTENT, BOOL, "0"}}, {"AlwaysOnDM", {PERSISTENT | BACKUP, BOOL}},
{"AlwaysOnDM", {PERSISTENT, BOOL}},
{"ApiCache_Device", {PERSISTENT, STRING}}, {"ApiCache_Device", {PERSISTENT, STRING}},
{"ApiCache_FirehoseStats", {PERSISTENT, JSON}}, {"ApiCache_FirehoseStats", {PERSISTENT, JSON}},
{"AssistNowToken", {PERSISTENT, STRING}}, {"AssistNowToken", {PERSISTENT, STRING}},
@@ -30,39 +29,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, BOOL}}, {"AlphaLongitudinalEnabled", {PERSISTENT | DEVELOPMENT_ONLY | BACKUP, BOOL}},
{"ExperimentalLongitudinalEnabled", {PERSISTENT, BOOL}}, {"ExperimentalMode", {PERSISTENT | BACKUP, BOOL}},
{"ExperimentalMode", {PERSISTENT, BOOL}}, {"ExperimentalModeConfirmed", {PERSISTENT | BACKUP, BOOL}},
{"ExperimentalModeConfirmed", {PERSISTENT, BOOL}},
{"PersistExperimentalState", {PERSISTENT, BOOL, "0", "0", 1}},
{"PersistedCEStatus", {PERSISTENT, INT, "0", "0"}},
{"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}},
@@ -70,7 +66,7 @@ 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, "main_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}},
@@ -81,15 +77,15 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"LastUpdateRouteCount", {PERSISTENT, INT, "0"}}, {"LastUpdateRouteCount", {PERSISTENT, INT, "0"}},
{"LastUpdateTime", {PERSISTENT, TIME}}, {"LastUpdateTime", {PERSISTENT, TIME}},
{"LastUpdateUptimeOnroad", {PERSISTENT, FLOAT, "0.0"}}, {"LastUpdateUptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
{"LiveDelay", {PERSISTENT, BYTES}}, {"LiveDelay", {PERSISTENT | BACKUP, BYTES}},
{"LiveParameters", {PERSISTENT, JSON}}, {"LiveParameters", {PERSISTENT, JSON}},
{"LiveParametersV2", {PERSISTENT, BYTES}}, {"LiveParametersV2", {PERSISTENT, BYTES}},
{"LiveTorqueParameters", {PERSISTENT | DONT_LOG, BYTES}}, {"LiveTorqueParameters", {PERSISTENT | DONT_LOG, BYTES}},
{"LateralManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
{"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_CarUnrecognized", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}}, {"Offroad_CarUnrecognized", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
@@ -105,23 +101,22 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"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}},
{"OnroadCycleRequested", {CLEAR_ON_MANAGER_START, BOOL}}, {"OnroadCycleRequested", {CLEAR_ON_MANAGER_START, BOOL}},
{"OpenpilotEnabledToggle", {PERSISTENT, BOOL, "1"}}, {"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}}, {"PandaSomResetTriggered", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
{"PandaSignatures", {CLEAR_ON_MANAGER_START, BYTES}}, {"PandaSignatures", {CLEAR_ON_MANAGER_START, BYTES}},
{"PrimeType", {PERSISTENT, INT}}, {"PrimeType", {PERSISTENT, INT}},
{"RecordAudio", {PERSISTENT, BOOL}}, {"RecordAudio", {PERSISTENT | BACKUP, BOOL}},
{"RecordAudioFeedback", {PERSISTENT, BOOL, "0"}}, {"RecordAudioFeedback", {PERSISTENT | BACKUP, BOOL, "0"}},
{"RecordFront", {PERSISTENT, BOOL}}, {"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}}, {"ShowDebugInfo", {PERSISTENT, BOOL}},
{"ShowAllToggles", {PERSISTENT, BOOL, "0", "0", 3}},
{"UsePrebuilt", {PERSISTENT, BOOL, "1"}},
{"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}},
@@ -139,422 +134,147 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}}, {"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
{"Version", {PERSISTENT, STRING}}, {"Version", {PERSISTENT, STRING}},
// StarPilot variables // --- sunnypilot params --- //
{"AccelerationPath", {PERSISTENT, BOOL, "1", "0", 2}}, {"ApiCache_DriveStats", {PERSISTENT, JSON}},
{"AccelerationProfile", {PERSISTENT, INT, "2", "0", 0}}, {"AutoLaneChangeBsmDelay", {PERSISTENT | BACKUP, BOOL, "0"}},
{"AdjacentLeadsUI", {PERSISTENT, BOOL, "1", "0", 3}}, {"AutoLaneChangeTimer", {PERSISTENT | BACKUP, INT, "0"}},
{"AdjacentPath", {PERSISTENT, BOOL, "0", "0", 3}}, {"BlinkerLateralReengageDelay", {PERSISTENT | BACKUP, INT, "0"}}, // seconds
{"AdjacentPathMetrics", {PERSISTENT, BOOL, "0", "0", 3}}, {"BlinkerMinLateralControlSpeed", {PERSISTENT | BACKUP, INT, "20"}}, // MPH or km/h
{"AdvancedCustomUI", {PERSISTENT, BOOL, "0", "0", 2}}, {"BlinkerPauseLateralControl", {PERSISTENT | BACKUP, INT, "0"}},
{"AdvancedLateralTune", {PERSISTENT, BOOL, "1", "0", 2}}, {"Brightness", {PERSISTENT | BACKUP, INT, "0"}},
{"AdvancedLongitudinalTune", {PERSISTENT, BOOL, "1", "0", 3}}, {"CarList", {PERSISTENT, JSON}},
{"AggressiveFollow", {PERSISTENT, FLOAT, "1.25", "1.25", 2}}, {"CarParamsSP", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BYTES}},
{"AggressiveFollowHigh", {PERSISTENT, FLOAT, "1.25", "1.25", 2}}, {"CarParamsSPCache", {CLEAR_ON_MANAGER_START, BYTES}},
{"AggressiveJerkAcceleration", {PERSISTENT, FLOAT, "50.0", "50.0", 3}}, {"CarParamsSPPersistent", {PERSISTENT, BYTES}},
{"AggressiveJerkDanger", {PERSISTENT, FLOAT, "100.0", "100.0", 3}}, {"CarPlatformBundle", {PERSISTENT | BACKUP, JSON}},
{"AggressiveJerkDeceleration", {PERSISTENT, FLOAT, "50.0", "50.0", 3}}, {"ChevronInfo", {PERSISTENT | BACKUP, INT, "4"}},
{"AggressiveJerkSpeed", {PERSISTENT, FLOAT, "50.0", "50.0", 3}}, {"CompletedSunnylinkConsentVersion", {PERSISTENT, STRING, "0"}},
{"AggressiveJerkSpeedDecrease", {PERSISTENT, FLOAT, "50.0", "50.0", 3}}, {"CustomAccIncrementsEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
{"AlertVolumeControl", {PERSISTENT, BOOL, "0", "0", 2}}, {"CustomAccLongPressIncrement", {PERSISTENT | BACKUP, INT, "5"}},
{"AlwaysOnLateral", {PERSISTENT, BOOL, "1", "0", 0}}, {"CustomAccShortPressIncrement", {PERSISTENT | BACKUP, INT, "1"}},
{"AlwaysOnLateralLKAS", {PERSISTENT, BOOL, "1", "0", 2}}, {"DeviceBootMode", {PERSISTENT | BACKUP, INT, "0"}},
{"ApiCache_DriveStats", {PERSISTENT, JSON, "{}", "{}"}}, {"DevUIInfo", {PERSISTENT | BACKUP, INT, "0"}},
{"AutomaticallyDownloadModels", {PERSISTENT, BOOL, "1", "0", 1}}, {"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}},
{"AutomaticUpdates", {PERSISTENT, BOOL, "1", "1", 0}}, {"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}},
{"AvailableModelNames", {PERSISTENT, STRING, "", "", 1}}, {"GreenLightAlert", {PERSISTENT | BACKUP, BOOL, "0"}},
{"AvailableModelSeries", {PERSISTENT, STRING, "", "", 1}}, {"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}},
{"AvailableModels", {PERSISTENT, STRING, "", "", 1}}, {"HasAcceptedTermsSP", {PERSISTENT, STRING, "0"}},
{"BlacklistedModels", {PERSISTENT, STRING, "", "", 2}}, {"HideVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
{"BootLogo", {PERSISTENT, STRING, "starpilot", "stock", 0}}, {"IntelligentCruiseButtonManagement", {PERSISTENT | BACKUP , BOOL}},
{"BuildMetadata", {PERSISTENT, STRING, "", "", 0}}, {"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}},
{"BlindSpotMetrics", {PERSISTENT, BOOL, "1", "0", 3}}, {"IsDevelopmentBranch", {CLEAR_ON_MANAGER_START, BOOL}},
{"BlindSpotPath", {PERSISTENT, BOOL, "1", "0", 1}}, {"IsReleaseSpBranch", {CLEAR_ON_MANAGER_START, BOOL}},
{"BelowSteerSpeedVolume", {PERSISTENT, INT, "101", "101", 2}}, {"LastGPSPositionLLK", {PERSISTENT, STRING}},
{"BorderMetrics", {PERSISTENT, BOOL, "0", "0", 3}}, {"LeadDepartAlert", {PERSISTENT | BACKUP, BOOL, "0"}},
{"CalibratedLateralAcceleration", {PERSISTENT, FLOAT, "2.0", "2.0", 2}}, {"MaxTimeOffroad", {PERSISTENT | BACKUP, INT, "1800"}},
{"CalibrationProgress", {PERSISTENT, FLOAT, "0.0", "0.0", 3}}, {"ModelRunnerTypeCache", {CLEAR_ON_ONROAD_TRANSITION, INT}},
{"CameraView", {PERSISTENT, INT, "3", "0", 2}}, {"OffroadMode", {CLEAR_ON_MANAGER_START, BOOL}},
{"CancelDownloadMaps", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}}, {"Offroad_TiciSupport", {CLEAR_ON_MANAGER_START, JSON}},
{"CancelModelDownload", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}}, {"OnroadScreenOffBrightness", {PERSISTENT | BACKUP, INT, "0"}},
{"CancelThemeDownload", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}}, {"OnroadScreenOffBrightnessMigrated", {PERSISTENT | BACKUP, STRING, "0.0"}},
{"CarMake", {PERSISTENT, STRING, "mock", "mock", 0}}, {"OnroadScreenOffTimer", {PERSISTENT | BACKUP, INT, "15"}},
{"CarModel", {PERSISTENT, STRING, "MOCK", "MOCK", 0}}, {"OnroadScreenOffTimerMigrated", {PERSISTENT | BACKUP, STRING, "0.0"}},
{"CarModelName", {PERSISTENT, STRING, "", "", 0}}, {"OnroadUploads", {PERSISTENT | BACKUP, BOOL, "1"}},
{"CECurves", {PERSISTENT, BOOL, "0", "0", 1}}, {"QuickBootToggle", {PERSISTENT | BACKUP, BOOL, "0"}},
{"CECurvesLead", {PERSISTENT, BOOL, "0", "0", 1}}, {"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}},
{"CELead", {PERSISTENT, BOOL, "1", "0", 1}}, {"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}},
{"CEModelStopTime", {PERSISTENT, FLOAT, "7.0", "0.0", 2}}, {"RocketFuel", {PERSISTENT | BACKUP, BOOL, "0"}},
{"CESignalLaneDetection", {PERSISTENT, BOOL, "1", "0", 2}}, {"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}},
{"CESignalSpeed", {PERSISTENT, FLOAT, "0.0", "0.0", 2}}, {"ShowTurnSignals", {PERSISTENT | BACKUP, BOOL, "0"}},
{"CESlowerLead", {PERSISTENT, BOOL, "1", "0", 1}}, {"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}},
{"CESpeed", {PERSISTENT, FLOAT, "0.0", "0.0", 1}}, {"TrueVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
{"CESpeedLead", {PERSISTENT, FLOAT, "0.0", "0.0", 1}},
{"CEStatus", {CLEAR_ON_OFFROAD_TRANSITION, INT, "0", "0"}}, // MADS params
{"CEStopLights", {PERSISTENT, BOOL, "1", "0", 1}}, {"Mads", {PERSISTENT | BACKUP, BOOL, "1"}},
{"CEStoppedLead", {PERSISTENT, BOOL, "1", "0", 1}}, {"MadsMainCruiseAllowed", {PERSISTENT | BACKUP, BOOL, "1"}},
{"ClusterOffset", {PERSISTENT, FLOAT, "1.015", "1.015", 2}}, {"MadsSteeringMode", {PERSISTENT | BACKUP, INT, "0"}},
{"ColorScheme", {PERSISTENT, STRING, "frog", "stock", 0}}, {"MadsUnifiedEngagementMode", {PERSISTENT | BACKUP, BOOL, "1"}},
{"ColorToDownload", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"BootLogoToDownload", {CLEAR_ON_MANAGER_START, STRING, "", ""}}, // Model Manager params
{"Compass", {PERSISTENT, BOOL, "0", "0", 1}}, {"ModelManager_ActiveBundle", {PERSISTENT, JSON}},
{"CommunityFavorites", {PERSISTENT, STRING, "", "", 1}}, {"ModelManager_ClearCache", {CLEAR_ON_MANAGER_START, BOOL}},
{"ConditionalExperimental", {PERSISTENT, BOOL, "1", "0", 1}}, {"ModelManager_DownloadIndex", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, INT}},
{"CurvatureData", {PERSISTENT | DONT_LOG, JSON, "{}", "{}"}}, {"ModelManager_Favs", {PERSISTENT | BACKUP, STRING}},
{"CurveSpeedController", {PERSISTENT, BOOL, "1", "0", 1}}, {"ModelManager_LastSyncTime", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, INT, "0"}},
{"CustomAlerts", {PERSISTENT, BOOL, "0", "0", 0}}, {"ModelManager_ModelsCache", {PERSISTENT | BACKUP, JSON}},
{"CustomAccelProfile", {PERSISTENT, BOOL, "0", "0", 3}},
{"CustomAccelProfileInitialized", {PERSISTENT, BOOL, "0", "0", 3}}, // Neural Network Lateral Control
{"CustomAccelProfile0MPH", {PERSISTENT, FLOAT, "3.0", "3.0", 3}}, {"NeuralNetworkLateralControl", {PERSISTENT | BACKUP, BOOL, "0"}},
{"CustomAccelProfile11MPH", {PERSISTENT, FLOAT, "2.5", "2.5", 3}},
{"CustomAccelProfile22MPH", {PERSISTENT, FLOAT, "2.0", "2.0", 3}}, // sunnylink params
{"CustomAccelProfile34MPH", {PERSISTENT, FLOAT, "1.5", "1.5", 3}}, {"EnableSunnylinkUploader", {PERSISTENT | BACKUP, BOOL}},
{"CustomAccelProfile45MPH", {PERSISTENT, FLOAT, "1.0", "1.0", 3}}, {"LastSunnylinkPingTime", {CLEAR_ON_MANAGER_START, INT}},
{"CustomAccelProfile56MPH", {PERSISTENT, FLOAT, "0.8", "0.8", 3}}, {"ParamsVersion", {PERSISTENT, INT}},
{"CustomAccelProfile89MPH", {PERSISTENT, FLOAT, "0.6", "0.6", 3}}, {"SunnylinkCache_Roles", {PERSISTENT, STRING}},
{"CustomCruise", {PERSISTENT, FLOAT, "1.0", "1.0", 2}}, {"SunnylinkCache_Users", {PERSISTENT, STRING}},
{"CustomCruiseLong", {PERSISTENT, FLOAT, "5.0", "5.0", 2}}, {"SunnylinkDongleId", {PERSISTENT, STRING}},
{"CustomPersonalities", {PERSISTENT, BOOL, "0", "0", 2}}, {"SunnylinkdPid", {PERSISTENT, INT}},
{"TrafficPersonalityProfile", {PERSISTENT, BOOL, "1", "1", 2}}, {"SunnylinkEnabled", {PERSISTENT, BOOL, "1"}},
{"AggressivePersonalityProfile", {PERSISTENT, BOOL, "1", "1", 2}}, {"SunnylinkTempFault", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL, "0"}},
{"StandardPersonalityProfile", {PERSISTENT, BOOL, "1", "1", 2}},
{"RelaxedPersonalityProfile", {PERSISTENT, BOOL, "1", "1", 2}}, // Backup Manager params
{"CustomThemes", {PERSISTENT, BOOL, "1", "0", 0}}, {"BackupManager_CreateBackup", {PERSISTENT, BOOL}},
{"CustomUI", {PERSISTENT, BOOL, "1", "0", 1}}, {"BackupManager_RestoreVersion", {PERSISTENT, STRING}},
{"DebugMode", {CLEAR_ON_OFFROAD_TRANSITION, BOOL, "0", "0"}},
{"DecelerationProfile", {PERSISTENT, INT, "1", "0", 2}}, // sunnypilot car specific params
{"DeveloperMetrics", {PERSISTENT, BOOL, "1", "0", 3}}, {"HyundaiLongitudinalTuning", {PERSISTENT | BACKUP, INT, "0"}},
{"DeveloperSidebar", {PERSISTENT, BOOL, "1", "0", 3}}, {"SubaruStopAndGo", {PERSISTENT | BACKUP, BOOL, "0"}},
{"DeveloperSidebarMetric1", {PERSISTENT, INT, "1", "0", 3}}, {"SubaruStopAndGoManualParkingBrake", {PERSISTENT | BACKUP, BOOL, "0"}},
{"DeveloperSidebarMetric2", {PERSISTENT, INT, "2", "0", 3}}, {"TeslaCoopSteering", {PERSISTENT | BACKUP, BOOL, "0"}},
{"DeveloperSidebarMetric3", {PERSISTENT, INT, "3", "0", 3}}, {"ToyotaEnforceStockLongitudinal", {PERSISTENT | BACKUP, BOOL, "0"}},
{"DeveloperSidebarMetric4", {PERSISTENT, INT, "4", "0", 3}}, {"ToyotaStopAndGoHack", {PERSISTENT | BACKUP, BOOL, "0"}},
{"DeveloperSidebarMetric5", {PERSISTENT, INT, "5", "0", 3}},
{"DeveloperSidebarMetric6", {PERSISTENT, INT, "6", "0", 3}}, {"DynamicExperimentalControl", {PERSISTENT | BACKUP, BOOL, "0"}},
{"DeveloperSidebarMetric7", {PERSISTENT, INT, "7", "0", 3}}, {"BlindSpot", {PERSISTENT | BACKUP, BOOL, "0"}},
{"DeveloperUI", {PERSISTENT, BOOL, "0", "0", 3}},
{"DeveloperWidgets", {PERSISTENT, BOOL, "1", "0", 3}}, // sunnypilot model params
{"DeviceManagement", {PERSISTENT, BOOL, "1", "0", 1}}, {"CameraOffset", {PERSISTENT | BACKUP, FLOAT, "0.0"}},
{"DeviceShutdown", {PERSISTENT, INT, "9", "33", 1}}, {"LagdToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
{"DisableOnroadUploads", {PERSISTENT, BOOL, "0", "0", 2}}, {"LagdToggleDelay", {PERSISTENT | BACKUP, FLOAT, "0.2"}},
{"DisableOpenpilotLongitudinal", {PERSISTENT, BOOL, "0", "0", 0}}, {"LagdValueCache", {PERSISTENT, FLOAT, "0.2"}},
{"DiscordUsername", {PERSISTENT, STRING, "", "", 0}}, {"LaneTurnDesire", {PERSISTENT | BACKUP, BOOL, "0"}},
{"DisengageVolume", {PERSISTENT, INT, "101", "101", 2}}, {"LaneTurnValue", {PERSISTENT | BACKUP, FLOAT, "19.0"}},
{"DistanceButtonControl", {PERSISTENT, INT, "1", "0", 2}}, {"PlanplusControl", {PERSISTENT | BACKUP, FLOAT, "1.0"}},
{"DistanceIconPack", {PERSISTENT, STRING, "stock", "stock", 0}},
{"DistanceIconToDownload", {CLEAR_ON_MANAGER_START, STRING, "", ""}}, // mapd
{"DownloadableBootLogos", {PERSISTENT, STRING, "", ""}}, {"MapAdvisorySpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, FLOAT}},
{"DownloadableColors", {PERSISTENT, STRING, "", ""}}, {"MapdVersion", {PERSISTENT, STRING}},
{"DownloadableDistanceIcons", {PERSISTENT, STRING, "", ""}}, {"MapSpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, FLOAT, "0.0"}},
{"DownloadableIcons", {PERSISTENT, STRING, "", ""}}, {"NextMapSpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, JSON}},
{"DownloadableSignals", {PERSISTENT, STRING, "", ""}}, {"Offroad_OSMUpdateRequired", {CLEAR_ON_MANAGER_START, JSON}},
{"DownloadableSounds", {PERSISTENT, STRING, "", ""}}, {"OsmDbUpdatesCheck", {CLEAR_ON_MANAGER_START, BOOL}}, // mapd database update happens with device ON, reset on boot
{"DownloadableWheels", {PERSISTENT, STRING, "", ""}}, {"OSMDownloadBounds", {PERSISTENT, STRING}},
{"DownloadAllModels", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}}, {"OsmDownloadedDate", {PERSISTENT, STRING, "0.0"}},
{"DownloadMaps", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}}, {"OSMDownloadLocations", {PERSISTENT, JSON}},
{"DriverCamera", {PERSISTENT, BOOL, "0", "0", 1}}, {"OSMDownloadProgress", {CLEAR_ON_MANAGER_START, JSON}},
{"Model", {PERSISTENT, STRING, "sc2", "sc2", 1}}, {"OsmLocal", {PERSISTENT, BOOL}},
{"ModelVersion", {PERSISTENT, STRING, "v11", "v11", 1}}, {"OsmLocationName", {PERSISTENT, STRING}},
{"DrivingModel", {PERSISTENT, STRING, "sc2", "sc2", 1}}, {"OsmLocationTitle", {PERSISTENT, STRING}},
{"DrivingModelName", {PERSISTENT, STRING, "South Carolina", "South Carolina", 1}}, {"OsmLocationUrl", {PERSISTENT, STRING}},
{"DrivingModelVersion", {PERSISTENT, STRING, "v11", "v11", 1}}, {"OsmStateName", {PERSISTENT, STRING, "All"}},
{"DynamicPathWidth", {PERSISTENT, BOOL, "0", "0", 2}}, {"OsmStateTitle", {PERSISTENT, STRING}},
{"DynamicPedalsOnUI", {PERSISTENT, BOOL, "1", "0", 1}}, {"OsmWayTest", {PERSISTENT, STRING}},
{"EngageVolume", {PERSISTENT, INT, "101", "101", 2}}, {"RoadName", {CLEAR_ON_ONROAD_TRANSITION, STRING}},
{"EVTuning", {PERSISTENT, BOOL, "0", "0", 3}}, {"RoadNameToggle", {PERSISTENT | BACKUP, BOOL, "0"}},
{"Fahrenheit", {PERSISTENT, BOOL, "0", "0", 3}},
{"FlashPanda", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}}, // Speed Limit
{"GMPedalLongitudinal", {PERSISTENT, BOOL, "1", "1", 2}}, {"SpeedLimitMode", {PERSISTENT | BACKUP, INT, "1"}},
{"LongPitch", {PERSISTENT, BOOL, "1", "0", 2}}, {"SpeedLimitOffsetType", {PERSISTENT | BACKUP, INT, "0"}},
{"RemoteStartBootsComma", {PERSISTENT, BOOL, "0", "0"}}, {"SpeedLimitPolicy", {PERSISTENT | BACKUP, INT, "3"}},
{"RemapCancelToDistance", {PERSISTENT, BOOL, "0", "0"}}, {"SpeedLimitValueOffset", {PERSISTENT | BACKUP, INT, "0"}},
{"ForceAutoTune", {PERSISTENT, BOOL, "0", "0", 3}},
{"ForceAutoTuneOff", {PERSISTENT, BOOL, "1", "0", 2}}, // Smart Cruise Control
{"ForceFingerprint", {PERSISTENT, BOOL, "0", "0", 2}}, {"MapTargetVelocities", {CLEAR_ON_ONROAD_TRANSITION, STRING}},
{"ForceOffroad", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}}, {"SmartCruiseControlMap", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ForceOnroad", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}}, {"SmartCruiseControlVision", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ForceStops", {PERSISTENT, BOOL, "0", "0", 2}},
{"ForceStandstill", {PERSISTENT, BOOL, "0", "0", 2}}, // Torque lateral control custom params
{"ForceTorqueController", {PERSISTENT, BOOL, "0", "0", 3}}, {"CustomTorqueParams", {PERSISTENT | BACKUP , BOOL}},
{"FPSCounter", {PERSISTENT, BOOL, "1", "0", 3}}, {"EnforceTorqueControl", {PERSISTENT | BACKUP, BOOL}},
{"StarPilotApiToken", {PERSISTENT | DONT_LOG, STRING, "", "", 0}}, {"LiveTorqueParamsToggle", {PERSISTENT | BACKUP , BOOL}},
{"StarPilotCarParams", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BYTES, "", ""}}, {"LiveTorqueParamsRelaxedToggle", {PERSISTENT | BACKUP , BOOL}},
{"StarPilotCarParamsPersistent", {PERSISTENT, BYTES, "", ""}}, {"TorqueControlTune", {PERSISTENT | BACKUP, FLOAT, "0.0"}},
{"StarPilotDongleId", {PERSISTENT | DONT_LOG, STRING, "", "", 0}}, {"TorqueParamsOverrideEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
{"StarPilotStats", {PERSISTENT | DONT_LOG, JSON, "{}", "{}"}}, {"TorqueParamsOverrideFriction", {PERSISTENT | BACKUP, FLOAT, "0.1"}},
{"StarPilotTogglesUpdated", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}}, {"TorqueParamsOverrideLatAccelFactor", {PERSISTENT | BACKUP, FLOAT, "2.5"}},
{"FrogsGoMoosTweak", {PERSISTENT, BOOL, "1", "0", 2}},
{"GoatScream", {PERSISTENT, BOOL, "0", "0", 1}},
{"GoatScreamCriticalAlerts", {PERSISTENT, BOOL, "0", "0", 1}},
{"GreenLightAlert", {PERSISTENT, BOOL, "0", "0", 0}},
{"HideAlerts", {PERSISTENT, BOOL, "0", "0", 2}},
{"HideLeadMarker", {PERSISTENT, BOOL, "0", "0", 2}},
{"HideMaxSpeed", {PERSISTENT, BOOL, "0", "0", 2}},
{"HideSpeed", {PERSISTENT, BOOL, "0", "0", 2}},
{"HideSpeedLimit", {PERSISTENT, BOOL, "0", "0", 2}},
{"HigherBitrate", {PERSISTENT, BOOL, "0", "0", 2}},
{"HolidayThemes", {PERSISTENT, BOOL, "1", "0", 0}},
{"HumanAcceleration", {PERSISTENT, BOOL, "0", "0", 2}},
{"HumanFollowing", {PERSISTENT, BOOL, "0", "0", 2}},
{"HumanLaneChanges", {PERSISTENT, BOOL, "0", "0", 2}},
{"IconPack", {PERSISTENT, STRING, "frog-animated", "stock", 0}},
{"IconToDownload", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"IncreasedStoppedDistance", {PERSISTENT, FLOAT, "0.0", "0.0", 1}},
{"IncreasedStoppedDistanceLowVisibility", {PERSISTENT, FLOAT, "0.0", "0.0", 2}},
{"IncreasedStoppedDistanceRain", {PERSISTENT, FLOAT, "0.0", "0.0", 2}},
{"IncreasedStoppedDistanceRainStorm", {PERSISTENT, FLOAT, "0.0", "0.0", 2}},
{"IncreasedStoppedDistanceSnow", {PERSISTENT, FLOAT, "0.0", "0.0", 2}},
{"IncreaseFollowingLowVisibility", {PERSISTENT, FLOAT, "0.0", "0.0", 2}},
{"IncreaseFollowingRain", {PERSISTENT, FLOAT, "0.0", "0.0", 2}},
{"IncreaseFollowingRainStorm", {PERSISTENT, FLOAT, "0.0", "0.0", 2}},
{"IncreaseFollowingSnow", {PERSISTENT, FLOAT, "0.0", "0.0", 2}},
{"IncreaseThermalLimits", {PERSISTENT, BOOL, "0", "0", 2}},
{"IssueReported", {CLEAR_ON_MANAGER_START, JSON, "{}", "{}"}},
{"KonikDongleId", {PERSISTENT, STRING, "", "", 0}},
{"KonikMinutes", {PERSISTENT, INT, "0", "0", 0}},
{"LaneChanges", {PERSISTENT, BOOL, "1", "1", 0}},
{"LaneChangeTime", {PERSISTENT, FLOAT, "1.0", "0.0", 1}},
{"LaneDetectionWidth", {PERSISTENT, FLOAT, "0.0", "0.0", 1}},
{"LaneLinesWidth", {PERSISTENT, FLOAT, "4.0", "2.0", 2}},
{"LastMapsUpdate", {PERSISTENT, STRING, "", ""}},
{"LateralTune", {PERSISTENT, BOOL, "1", "0", 1}},
{"LeadDepartingAlert", {PERSISTENT, BOOL, "0", "0", 0}},
{"LeadDetectionThreshold", {PERSISTENT, INT, "35", "50", 3}},
{"LeadInfo", {PERSISTENT, BOOL, "1", "0", 3}},
{"LKASButtonControl", {PERSISTENT, INT, "5", "0", 2}},
{"LockDoors", {PERSISTENT, BOOL, "1", "0", 0}},
{"LockDoorsTimer", {PERSISTENT, INT, "0", "0", 0}},
{"LongDistanceButtonControl", {PERSISTENT, INT, "5", "0", 2}},
{"LongitudinalActuatorDelay", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"LongitudinalActuatorDelayStock", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"LateralManeuverStatus", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, JSON, "{}", "{}"}},
{"LongitudinalManeuverPaddleMode", {PERSISTENT, STRING, "auto", "auto"}},
{"LongitudinalManeuverStatus", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, JSON, "{}", "{}"}},
{"LongitudinalTune", {PERSISTENT, BOOL, "1", "0", 0}},
{"LoudBlindspotAlert", {PERSISTENT, BOOL, "0", "0", 0}},
{"LowVoltageShutdown", {PERSISTENT, FLOAT, "11.8", "11.8", 3}},
{"ManualUpdateInitiated", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
{"MapAcceleration", {PERSISTENT, BOOL, "0", "0", 1}},
{"MapboxPublicKey", {PERSISTENT | DONT_LOG, STRING, "", "", 0}},
{"MapBoxRequests", {PERSISTENT, JSON, "{}", "{}"}},
{"MapboxSecretKey", {PERSISTENT | DONT_LOG, STRING, "", "", 0}},
{"MapDeceleration", {PERSISTENT, BOOL, "0", "0", 1}},
{"MapdSettings", {PERSISTENT, JSON, "{}", "{}"}},
{"MapGears", {PERSISTENT, BOOL, "0", "0", 2}},
{"MapsSelected", {PERSISTENT, STRING, "", "", 0}},
{"MapSpeedLimit", {CLEAR_ON_MANAGER_START, FLOAT, "0.0", "0.0"}},
{"NextMapSpeedLimit", {CLEAR_ON_MANAGER_START, JSON, "{}", "{}"}},
{"VisionSpeedLimit", {CLEAR_ON_MANAGER_START, FLOAT, "0.0", "0.0"}},
{"VisionSpeedLimitConfidence", {CLEAR_ON_MANAGER_START, FLOAT, "0.0", "0.0"}},
{"VisionSpeedLimitBookmarkCount", {CLEAR_ON_MANAGER_START, INT, "0", "0"}},
{"VisionSpeedLimitDebugSession", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"VisionSpeedLimitLastEvent", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"VisionSpeedLimitStatus", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"VisionSpeedLimitStream", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"MaxDesiredAcceleration", {PERSISTENT, FLOAT, "4.0", "2.0", 2}},
{"MinimumBackupSize", {PERSISTENT, INT, "0", "0"}},
{"MinimumLaneChangeSpeed", {PERSISTENT, FLOAT, "20.0", "20.0", 2}},
{"ModelDownloadProgress", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"ModelDrivesAndScores", {PERSISTENT, JSON, "{}", "{}"}},
{"ModelReleasedDates", {PERSISTENT, STRING, "", "", 1}},
{"ModelRandomizer", {PERSISTENT, BOOL, "0", "0", 2}},
{"ModelSortMode", {PERSISTENT, STRING, "alphabetical", "alphabetical", 1}},
{"ModelToDownload", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"ModelUI", {PERSISTENT, BOOL, "1", "0", 2}},
{"ModelVersions", {PERSISTENT, STRING, "", "", 1}},
{"NavigationUI", {PERSISTENT, BOOL, "1", "0", 1}},
{"NNFF", {PERSISTENT, BOOL, "0", "0", 2}},
{"NNFFLite", {PERSISTENT, BOOL, "0", "0", 2}},
{"NNFFModelName", {CLEAR_ON_MANAGER_START, STRING, "", "", 0}},
{"NoLogging", {PERSISTENT, BOOL, "0", "0", 2}},
{"NoUploads", {PERSISTENT, BOOL, "0", "0", 2}},
{"NudgelessLaneChange", {PERSISTENT, BOOL, "1", "0", 0}},
{"NumericalTemp", {PERSISTENT, BOOL, "1", "0", 3}},
{"Offset1", {PERSISTENT, FLOAT, "5.0", "0.0", 0}},
{"Offset2", {PERSISTENT, FLOAT, "5.0", "0.0", 0}},
{"Offset3", {PERSISTENT, FLOAT, "5.0", "0.0", 0}},
{"Offset4", {PERSISTENT, FLOAT, "5.0", "0.0", 0}},
{"Offset5", {PERSISTENT, FLOAT, "10.0", "0.0", 0}},
{"Offset6", {PERSISTENT, FLOAT, "10.0", "0.0", 0}},
{"Offset7", {PERSISTENT, FLOAT, "10.0", "0.0", 0}},
{"OneLaneChange", {PERSISTENT, BOOL, "1", "0", 2}},
{"OnroadDistanceButton", {PERSISTENT, BOOL, "0", "0", 0}},
{"OnroadDistanceButtonPressed", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
{"openpilotMinutes", {PERSISTENT, INT, "0", "0", 0}},
{"OverpassRequests", {PERSISTENT, JSON, "{}", "{}"}},
{"PathEdgeWidth", {PERSISTENT, FLOAT, "20.0", "0.0", 2}},
{"PathWidth", {PERSISTENT, FLOAT, "6.1", "5.9", 2}},
{"PauseAOLOnBrake", {PERSISTENT, BOOL, "0", "0", 1}},
{"PauseLateralOnSignal", {PERSISTENT, BOOL, "0", "0", 1}},
{"PauseLateralSpeed", {PERSISTENT, FLOAT, "0.0", "0.0", 1}},
{"PedalsOnUI", {PERSISTENT, BOOL, "0", "0", 1}},
{"PondPaired", {PERSISTENT, BOOL, "0", "0", 0}},
{"PondUploadPending", {PERSISTENT, BOOL, "0", "0", 0}},
{"PreferredSchedule", {PERSISTENT, INT, "2", "0", 0}},
{"PreviousSpeedLimit", {PERSISTENT, FLOAT, "0.0", "0.0"}},
{"PromptDistractedVolume", {PERSISTENT, INT, "101", "101", 2}},
{"PromptVolume", {PERSISTENT, INT, "101", "101", 2}},
{"QOLLateral", {PERSISTENT, BOOL, "1", "0", 1}},
{"QOLLongitudinal", {PERSISTENT, BOOL, "1", "0", 1}},
{"QOLVisuals", {PERSISTENT, BOOL, "1", "0", 0}},
{"RadarTracksUI", {PERSISTENT, BOOL, "0", "0", 3}},
{"RainbowPath", {PERSISTENT, BOOL, "0", "0", 1}},
{"RandomEvents", {PERSISTENT, BOOL, "0", "0", 1}},
{"RandomThemes", {PERSISTENT, BOOL, "0", "0", 1}},
{"RandomThemesHolidays", {PERSISTENT, BOOL, "0", "0", 1}},
{"ReduceAccelerationLowVisibility", {PERSISTENT, INT, "0", "0", 2}},
{"ReduceAccelerationRain", {PERSISTENT, INT, "0", "0", 2}},
{"ReduceAccelerationRainStorm", {PERSISTENT, INT, "0", "0", 2}},
{"ReduceAccelerationSnow", {PERSISTENT, INT, "0", "0", 2}},
{"ReduceLateralAccelerationLowVisibility", {PERSISTENT, INT, "0", "0", 2}},
{"ReduceLateralAccelerationRain", {PERSISTENT, INT, "0", "0", 2}},
{"ReduceLateralAccelerationRainStorm", {PERSISTENT, INT, "0", "0", 2}},
{"ReduceLateralAccelerationSnow", {PERSISTENT, INT, "0", "0", 2}},
{"RefuseVolume", {PERSISTENT, INT, "101", "101", 2}},
{"RelaxedFollow", {PERSISTENT, FLOAT, "1.75", "1.75", 2}},
{"RelaxedFollowHigh", {PERSISTENT, FLOAT, "1.75", "1.75", 2}},
{"RelaxedJerkAcceleration", {PERSISTENT, FLOAT, "50.0", "50.0", 3}},
{"RelaxedJerkDanger", {PERSISTENT, FLOAT, "100.0", "100.0", 3}},
{"RelaxedJerkDeceleration", {PERSISTENT, FLOAT, "50.0", "50.0", 3}},
{"RelaxedJerkSpeed", {PERSISTENT, FLOAT, "50.0", "50.0", 3}},
{"RelaxedJerkSpeedDecrease", {PERSISTENT, FLOAT, "50.0", "50.0", 3}},
{"ReverseCruise", {PERSISTENT, BOOL, "0", "0", 1}},
{"RecoveryPower", {PERSISTENT, FLOAT, "1.0", "1.0", 2}},
{"RoadEdgesWidth", {PERSISTENT, FLOAT, "2.0", "2.0", 2}},
{"RoadNameUI", {PERSISTENT, BOOL, "1", "0", 1}},
{"RotatingWheel", {PERSISTENT, BOOL, "1", "0", 1}},
{"ScreenBrightness", {PERSISTENT, INT, "101", "101", 2}},
{"ScreenBrightnessOnroad", {PERSISTENT, INT, "101", "101", 2}},
{"ScreenManagement", {PERSISTENT, BOOL, "1", "0", 1}},
{"ScreenRecorder", {PERSISTENT, BOOL, "1", "0", 2}},
{"ScreenTimeout", {PERSISTENT, INT, "30", "30", 2}},
{"ScreenTimeoutOnroad", {PERSISTENT, INT, "30", "10", 2}},
{"SecOCKeys", {PERSISTENT | DONT_LOG, STRING, "", "", 0}},
{"SafeMode", {PERSISTENT, BOOL, "0", "0", 0}},
{"SafeModeBackup", {PERSISTENT, JSON, "{}", "{}"}},
{"SetSpeedLimit", {PERSISTENT, BOOL, "0", "0", 1}},
{"SetSpeedOffset", {PERSISTENT, FLOAT, "0.0", "0.0", 2}},
{"ShowCEMStatus", {PERSISTENT, BOOL, "1", "0", 2}},
{"ShowCPU", {PERSISTENT, BOOL, "1", "0", 3}},
{"ShowCSCStatus", {PERSISTENT, BOOL, "1", "0", 2}},
{"ShowGPU", {PERSISTENT, BOOL, "0", "0", 3}},
{"ShowIP", {PERSISTENT, BOOL, "0", "0", 3}},
{"ShowMemoryUsage", {PERSISTENT, BOOL, "1", "0", 3}},
{"ShownToggleDescriptions", {PERSISTENT, JSON, "{}", "{}"}},
{"ShowSLCOffset", {PERSISTENT, BOOL, "1", "0", 0}},
{"ShowSpeedLimits", {PERSISTENT, BOOL, "1", "0", 1}},
{"ShowSteering", {PERSISTENT, BOOL, "0", "0", 3}},
{"ShowStoppingPoint", {PERSISTENT, BOOL, "1", "0", 3}},
{"ShowStoppingPointMetrics", {PERSISTENT, BOOL, "1", "0", 3}},
{"ShowStorageLeft", {PERSISTENT, BOOL, "0", "0", 3}},
{"ShowStorageUsed", {PERSISTENT, BOOL, "0", "0", 3}},
{"SidebarMetrics", {PERSISTENT, BOOL, "1", "0", 3}},
{"SidebarOpen", {PERSISTENT, BOOL, "0", "0", 0}},
{"SignalAnimation", {PERSISTENT, STRING, "frog", "stock", 0}},
{"SignalMetrics", {PERSISTENT, BOOL, "0", "0", 3}},
{"SignalToDownload", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"SimpleMode", {PERSISTENT, BOOL, "0", "0", 0}},
{"SLCConfirmation", {PERSISTENT, BOOL, "0", "0", 0}},
{"SLCConfirmationHigher", {PERSISTENT, BOOL, "0", "0", 0}},
{"SLCConfirmationLower", {PERSISTENT, BOOL, "0", "0", 0}},
{"SLCFallback", {PERSISTENT, INT, "2", "0", 1}},
{"SLCLookaheadHigher", {PERSISTENT, INT, "0", "0", 2}},
{"SLCLookaheadLower", {PERSISTENT, INT, "0", "0", 2}},
{"SLCMapboxFiller", {PERSISTENT, BOOL, "1", "0", 1}},
{"SLCOverride", {PERSISTENT, INT, "1", "0", 1}},
{"SLCPriority", {PERSISTENT, STRING, "", "", 2}},
{"SLCPriority1", {PERSISTENT, STRING, "Map Data", "Map Data", 2}},
{"SLCPriority2", {PERSISTENT, STRING, "Dashboard", "Dashboard", 2}},
{"SNGHack", {PERSISTENT, BOOL, "1", "0", 2}},
{"SoundPack", {PERSISTENT, STRING, "frog", "stock", 0}},
{"SoundToDownload", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"SpeedLimitAccepted", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
{"SpeedLimitChangedAlert", {PERSISTENT, BOOL, "0", "0", 0}},
{"SpeedLimitController", {PERSISTENT, BOOL, "0", "0", 0}},
{"SpeedLimitFiller", {PERSISTENT, BOOL, "0", "0", 0}},
{"SpeedLimits", {PERSISTENT | DONT_LOG, JSON, "[]", "[]"}},
{"SpeedLimitsFiltered", {PERSISTENT | DONT_LOG, JSON, "[]", "[]"}},
{"SpeedLimitSources", {PERSISTENT, BOOL, "0", "0", 3}},
{"VisionSpeedLimitAutoBookmark", {PERSISTENT, BOOL, "0", "0", 0}},
{"VisionSpeedLimitAutoPreserveSegment", {PERSISTENT, BOOL, "0", "0", 0}},
{"VisionSpeedLimitDetection", {PERSISTENT, BOOL, "0", "0", 0}},
{"VisionSpeedLimitTrainingCollector", {PERSISTENT, BOOL, "1", "1", 0}},
{"StandardFollow", {PERSISTENT, FLOAT, "1.45", "1.45", 2}},
{"StandardFollowHigh", {PERSISTENT, FLOAT, "1.45", "1.45", 2}},
{"StandardJerkAcceleration", {PERSISTENT, FLOAT, "50.0", "50.0", 3}},
{"StandardJerkDanger", {PERSISTENT, FLOAT, "100.0", "100.0", 3}},
{"StandardJerkDeceleration", {PERSISTENT, FLOAT, "50.0", "50.0", 3}},
{"StandardJerkSpeed", {PERSISTENT, FLOAT, "50.0", "50.0", 3}},
{"StandardJerkSpeedDecrease", {PERSISTENT, FLOAT, "50.0", "50.0", 3}},
{"StandbyMode", {PERSISTENT, BOOL, "0", "0", 1}},
{"StartAccel", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"StartAccelStock", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"StartupMessageBottom", {PERSISTENT, STRING, "Human-tested, frog-approved 🐸", "Always keep hands on wheel and eyes on road", 0}},
{"StartupMessageTop", {PERSISTENT, STRING, "Hop in and buckle up!", "Be ready to take over at any time", 0}},
{"StaticPedalsOnUI", {PERSISTENT, BOOL, "0", "0", 1}},
{"SteerDelay", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"SteerDelayStock", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"SteerFriction", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"SteerFrictionStock", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"SteerKP", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"SteerKPStock", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"SteerLatAccel", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"SteerLatAccelStock", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"SteerOffset", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"SteerOffsetStock", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"SteerRatio", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"SteerRatioStock", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"StockDongleId", {PERSISTENT, STRING, "", ""}},
{"StopAccel", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"StopAccelStock", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"StoppedTimer", {PERSISTENT, BOOL, "0", "0", 1}},
{"StopDistance", {PERSISTENT, FLOAT, "6.0", "6.0", 2}},
{"StoppingDecelRate", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"StoppingDecelRateStock", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"SwitchbackModeCooldown", {PERSISTENT, INT, "5", "0", 2}},
{"SwitchbackModeEnabled", {CLEAR_ON_OFFROAD_TRANSITION, BOOL, "0", "0"}},
{"SubaruSNG", {PERSISTENT, BOOL, "1", "0", 2}},
{"TacoTune", {PERSISTENT, BOOL, "0", "0", 2}},
{"TacoTuneHacks", {PERSISTENT, BOOL, "0", "0", 2}},
{"TestAlert", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"TetheringEnabled", {PERSISTENT, INT, "0", "0", 0}},
{"ThemeDownloadProgress", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"ThemesDownloaded", {PERSISTENT, JSON, "{}", "{}"}},
{"Timezone", {PERSISTENT, STRING, "", ""}},
{"TinygradUpdateAvailable", {PERSISTENT, BOOL, "0", "0", 1}},
{"ToyotaDoors", {PERSISTENT, BOOL, "1", "0", 0}},
{"TrafficFollow", {PERSISTENT, FLOAT, "0.5", "0.5", 2}},
{"TrafficJerkAcceleration", {PERSISTENT, FLOAT, "50.0", "50.0", 3}},
{"TrafficJerkDanger", {PERSISTENT, FLOAT, "100.0", "100.0", 3}},
{"TrafficJerkDeceleration", {PERSISTENT, FLOAT, "50.0", "50.0", 3}},
{"TrafficJerkSpeed", {PERSISTENT, FLOAT, "50.0", "50.0", 3}},
{"TrafficJerkSpeedDecrease", {PERSISTENT, FLOAT, "50.0", "50.0", 3}},
{"TruckTuning", {PERSISTENT, BOOL, "0", "0", 3}},
{"TuningLevel", {PERSISTENT, INT, "0", "0", 0}},
{"TuningLevelConfirmed", {PERSISTENT, BOOL, "0", "0", 0}},
{"TurnDesires", {PERSISTENT, BOOL, "0", "0", 2}},
{"UnlockDoors", {PERSISTENT, BOOL, "1", "0", 0}},
{"Updated", {PERSISTENT, STRING, "0", "0"}},
{"UpdateSpeedLimits", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
{"UpdateSpeedLimitsStatus", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
{"UpdateTinygrad", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
{"UpdateWheelImage", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
{"UseActiveTheme", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
{"UseKonikServer", {PERSISTENT, BOOL, "0", "0", 2}},
{"UseSI", {PERSISTENT, BOOL, "1", "1", 3}},
{"UserFavorites", {PERSISTENT, STRING, "", "", 1}},
{"UseVienna", {PERSISTENT, BOOL, "0", "0", 1}},
{"VEgoStarting", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"VEgoStartingStock", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"VEgoStopping", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"VEgoStoppingStock", {PERSISTENT, FLOAT, "0.0", "0.0", 3}},
{"VeryLongDistanceButtonControl", {PERSISTENT, INT, "6", "0", 2}},
{"VoltSNG", {PERSISTENT, BOOL, "0", "0", 2}},
{"WarningImmediateVolume", {PERSISTENT, INT, "101", "101", 2}},
{"WarningSoftVolume", {PERSISTENT, INT, "101", "101", 2}},
{"WeatherPresets", {PERSISTENT, BOOL, "0", "0", 2}},
{"WeatherToken", {PERSISTENT | DONT_LOG, STRING, "", "", 2}},
{"WheelControls", {PERSISTENT, STRING, "", "", 2}},
{"WheelIcon", {PERSISTENT, STRING, "frog", "stock", 0}},
{"WheelSpeed", {PERSISTENT, BOOL, "0", "0", 2}},
{"WheelToDownload", {CLEAR_ON_MANAGER_START, STRING, "", ""}},
}; };
+1518 -3074
View File
File diff suppressed because it is too large Load Diff
+11 -71
View File
@@ -18,11 +18,9 @@ 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
# StarPilot variables
DONT_LOG
cpdef enum ParamKeyType: cpdef enum ParamKeyType:
STRING STRING
BOOL BOOL
@@ -33,7 +31,7 @@ cdef extern from "common/params.h":
BYTES BYTES
cdef cppclass c_Params "Params": cdef cppclass c_Params "Params":
c_Params(string, bool) 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 remove(string) nogil int remove(string) nogil
@@ -46,14 +44,7 @@ cdef extern from "common/params.h":
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)
# StarPilot variables
ParamKeyFlag getKeyFlag(string) nogil
optional[string] getStockValue(string) nogil
int getTuningLevel(string) nogil
PYTHON_2_CPP = { PYTHON_2_CPP = {
(str, STRING): lambda v: v, (str, STRING): lambda v: v,
@@ -65,35 +56,12 @@ PYTHON_2_CPP = {
(list, JSON): json.dumps, (list, JSON): json.dumps,
(bytes, BYTES): lambda v: v, (bytes, BYTES): lambda v: v,
} }
def _decode_int(v):
decoded = v.decode("utf-8")
try:
return int(decoded)
except ValueError:
return int(float(decoded))
def _decode_time(v):
decoded = v.decode("utf-8")
try:
return datetime.datetime.fromisoformat(decoded)
except ValueError:
for fmt in ("%B %d, %Y - %I:%M%p", "%B %d, %Y - %I:%M %p"):
try:
return datetime.datetime.strptime(decoded, fmt)
except ValueError:
pass
raise
CPP_2_PYTHON = { CPP_2_PYTHON = {
STRING: lambda v: v.decode("utf-8"), STRING: lambda v: v.decode("utf-8"),
BOOL: lambda v: v == b"1", BOOL: lambda v: v == b"1",
INT: _decode_int, INT: int,
FLOAT: float, FLOAT: float,
TIME: _decode_time, TIME: lambda v: datetime.datetime.fromisoformat(v.decode("utf-8")),
JSON: json.loads, JSON: json.loads,
BYTES: lambda v: v, BYTES: lambda v: v,
} }
@@ -108,27 +76,14 @@ cdef class Params:
cdef c_Params* p cdef c_Params* p
cdef str d cdef str d
# StarPilot variables def __cinit__(self, d=""):
cdef bool m
cdef bool return_defaults
def __cinit__(self, d="", *, memory=False, return_defaults=False):
cdef string path = <string>d.encode() cdef string path = <string>d.encode()
# StarPilot variables
cdef bool c_memory = memory
with nogil: with nogil:
self.p = new c_Params(path, c_memory) self.p = new c_Params(path)
self.d = d self.d = d
# StarPilot variables
self.m = memory
self.return_defaults = return_defaults or memory
def __reduce__(self): def __reduce__(self):
return (type(self), (self.d, self.m, self.return_defaults)) return (type(self), (self.d,))
def __dealloc__(self): def __dealloc__(self):
del self.p del self.p
@@ -165,7 +120,7 @@ cdef class Params:
with nogil: with nogil:
val = self.p.get(k, block) val = self.p.get(k, block)
default_val = (default.value() if default.has_value() else None) if (return_default or self.return_defaults and not block) else None default_val = (default.value() if default.has_value() else None) if return_default else None
if val == b"": if val == b"":
if block: if block:
# If we got no value while running in blocked mode # If we got no value while running in blocked mode
@@ -227,8 +182,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)
@@ -240,18 +195,3 @@ cdef class Params:
cdef string k = self.check_key(key) cdef string k = self.check_key(key)
cdef ParamKeyType t = self.p.getKeyType(k) cdef ParamKeyType t = self.p.getKeyType(k)
return self._cpp2python(t, value, None, key) return self._cpp2python(t, value, None, key)
# StarPilot variables
def get_key_flag(self, key):
return self.p.getKeyFlag(self.check_key(key))
def get_stock_value(self, key):
cdef string k = self.check_key(key)
cdef ParamKeyType t = self.p.getKeyType(k)
cdef optional[string] stock = self.p.getStockValue(k)
return self._cpp2python(t, stock.value(), None, key) if stock.has_value() else None
def get_tuning_level(self, key):
cdef string k = self.check_key(key)
cdef optional[int] level = self.p.getTuningLevel(k)
return level.value() if level.has_value() else 0
Binary file not shown.
+3 -9
View File
@@ -3,15 +3,9 @@ from numbers import Number
class PIDController: class PIDController:
def __init__(self, k_p, k_i, 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
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.set_limits(pos_limit, neg_limit) self.set_limits(pos_limit, neg_limit)
+9 -5
View File
@@ -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");
} }
+4 -2
View File
@@ -1,4 +1,5 @@
import os import os
import platform
import shutil import shutil
import uuid import uuid
@@ -9,9 +10,10 @@ 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, create_dirs_on_enter: bool = True, 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(), "msgq_" + 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.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

Some files were not shown because too many files have changed in this diff Show More