Merge remote-tracking branch 'sunnypilot/sunnypilot/master' into nnlc-lateral-jerk

This commit is contained in:
Jason Wen
2024-08-05 14:14:16 -04:00
467 changed files with 39888 additions and 10955 deletions
+1 -1
View File
@@ -44,7 +44,7 @@ subaru:
tesla:
- changed-files:
- any-glob-to-all-files: 'selfdrive/car/telsa/*'
- any-glob-to-all-files: 'selfdrive/car/tesla/*'
toyota:
- changed-files:
+1 -1
View File
@@ -7,7 +7,7 @@ on:
env:
BASE_IMAGE: openpilot-base
DOCKER_REGISTRY: ghcr.io/commaai
RUN: docker run --shm-size 1G -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
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:
+41 -63
View File
@@ -10,38 +10,30 @@ 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.value }}
ci_runs: ${{ steps.ci_runs_setup.outputs.matrix }}
steps:
- id: ci_runs_setup
name: CI_RUNS=${{ env.CI_RUNS }}
run: |
CI_RUNS=${{ inputs.ci_runs || '50' }}
mylist="value=["
matrix=$(python3 -c "import json; print(json.dumps({ 'run_number' : list(range(${{ env.CI_RUNS }})) }))")
echo "matrix=$matrix" >> $GITHUB_OUTPUT
for i in $(seq 1 $CI_RUNS);
do
if [ $i != $CI_RUNS ]; then
mylist+="\"$i\", "
else
mylist+="\"$i\"]"
fi
done
echo "$mylist" >> $GITHUB_OUTPUT
echo "Number of CI runs for report: $CI_RUNS"
ci_matrix_run:
needs: [ setup ]
strategy:
fail-fast: false
matrix:
value: ${{fromJSON(needs.setup.outputs.ci_runs)}}
matrix: ${{fromJSON(needs.setup.outputs.ci_runs)}}
uses: commaai/openpilot/.github/workflows/ci_weekly_run.yaml@master
with:
run_number: ${{ matrix.value }}
run_number: ${{ matrix.run_number }}
report:
needs: [ci_matrix_run]
@@ -62,62 +54,48 @@ jobs:
})
var report = {}
jobs.slice(1, jobs.length-1).forEach(job => {
const jobName = job.name.split('/')[2].trim();
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: [], cancelled: [] };
switch (job.conclusion) {
case "success":
report[jobName].successes.push(job.html_url); break;
report[jobName].successes.push({ "run_number": run, "link": job.html_url}); break;
case "failure":
report[jobName].failures.push(job.html_url); break;
report[jobName].failures.push({ "run_number": run, "link": job.html_url }); break;
case "cancelled":
report[jobName].cancelled.push(job.html_url); break;
report[jobName].cancelled.push({ "run_number": run, "link": job.html_url }); break;
}
});
return JSON.stringify(report);
return JSON.stringify({"jobs": report});
- name: Add job results to summary
env:
JOB_RESULTS: ${{ fromJSON(steps.get-job-results.outputs.result) }}
run: |
echo $JOB_RESULTS > job_results.json
generate_html_table() {
echo "<table>"
echo "<thead>"
echo " <tr>"
echo " <th>Job</th>"
echo " <th>Succeeded ✅</th>"
echo " <th>Failed ❌</th>"
echo " <th>Cancelled (timed out) ⏰</th>"
echo " </tr>"
echo "</thead>"
jq -r '
"<tbody>",
keys[] as $job |
"<tr>",
" <td>\($job)</td>",
" <td>",
" <details>",
" <summary>(\(.[$job].successes | length))</summary>",
" \(.[$job].successes[])<br>",
" </details>",
" </td>",
" <td>",
" <details>",
" <summary>(\(.[$job].failures | length))</summary>",
" \(.[$job].failures[])<br>",
" </details>",
" </td>",
" <td>",
" <details>",
" <summary>(\(.[$job].cancelled | length))</summary>",
" \(.[$job].cancelled[])<br>",
" </details>",
" </td>",
"</tr>"
' job_results.json
echo "</tbody>"
echo "</table>"
}
echo "# CI Job Summary" >> $GITHUB_STEP_SUMMARY
generate_html_table >> $GITHUB_STEP_SUMMARY
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
+97
View File
@@ -0,0 +1,97 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "master", "*-c3", "master*" ]
pull_request:
branches: [ "master", "*-c3", "master*" ]
schedule:
- cron: '39 7 * * 2'
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: c-cpp
build-mode: autobuild
- language: javascript-typescript
build-mode: none
- language: python
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
+12 -18
View File
@@ -15,31 +15,24 @@ 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
env:
BASE_IMAGE: openpilot-base
BUILD: selfdrive/test/docker_build.sh base
RUN: docker run --shm-size 1G -v $GITHUB_WORKSPACE:/tmp/openpilot -w /tmp/openpilot -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:
docs:
name: build docs
runs-on: ubuntu-latest
timeout-minutes: 45
if: false # TODO: replace this with the new docs
timeout-minutes: 1
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
- name: Build openpilot
run: |
${{ env.RUN }} "scons -j$(nproc)"
# Build
- name: Build docs
run: |
${{ env.RUN }} "apt update && apt install -y doxygen && cd docs && make -j$(nproc) html"
# 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:
@@ -54,16 +47,17 @@ jobs:
source release/identity.sh
cd openpilot-docs
git checkout --orphan tmp
git rm -rf .
cp -r ../build/docs/html/ docs/
cp -r ../docs/README.md .
# 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 add -f .
git commit -m "build docs"
# docs live in different repo to not bloat openpilot's full clone size
+45
View File
@@ -0,0 +1,45 @@
name: jenkins scan
on:
issue_comment:
types: [created, edited]
jobs:
# TODO: gc old branches in a separate job in this workflow
scan-comments:
runs-on: ubuntu-latest
if: ${{ github.event.issue.pull_request }}
steps:
- name: Check for trigger phrase
id: check_comment
uses: actions/github-script@v7
with:
script: |
const triggerPhrase = "trigger-jenkins";
const comment = context.payload.comment.body;
const commenter = context.payload.comment.user.login;
const { data: permissions } = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: commenter
});
const hasWriteAccess = permissions.permission === 'write' || permissions.permission === 'admin';
return (hasWriteAccess && comment.includes(triggerPhrase));
result-encoding: json
- name: Checkout repository
if: steps.check_comment.outputs.result == 'true'
uses: actions/checkout@v4
with:
ref: refs/pull/${{ github.event.issue.number }}/head
- name: Push to tmp-jenkins branch
if: steps.check_comment.outputs.result == 'true'
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git checkout -b tmp-jenkins-${{ github.event.issue.number }}
GIT_LFS_SKIP_PUSH=1 git push -f origin tmp-jenkins-${{ github.event.issue.number }}
+46
View File
@@ -0,0 +1,46 @@
name: Mirror to GitLab
on:
push:
delete:
workflow_dispatch: # This enables manual triggering
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Wait for other instances of this workflow to conclude
uses: softprops/turnstyle@8db075d65b19bf94e6e8687b504db69938dc3c65
with:
same-branch-only: 'true'
abort-after-seconds: 300
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Checkout Repository
uses: actions/checkout@v3
with:
ref: ${{ github.ref }}
fetch-depth: 0 # Fetch full history
- name: Set up Git
run: |
git config --global user.name 'GitHub Action'
git config --global user.email 'action@github.com'
- name: Set up SSH
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Add GitLab public keys
run: |
ssh-keyscan -H gitlab.com >> ~/.ssh/known_hosts
# Note: If you have issues with "push rejected missing LFS" or something make sure you disabled LFS on the GITLAB repo if you intend to use a different LFS repo other than the target repo.
- name: Sync and commit changes
id: sync-and-commit
run: |
# Add GitLab remote
git remote add gitlab git@gitlab.com:sunnypilot/sunnyhaibin/sunnypilot-github-mirror.git
git push -u --force gitlab ${{ github.ref }}
+2 -6
View File
@@ -46,17 +46,13 @@ jobs:
python3 -m ensurepip --upgrade
pip3 install uv
uv lock --upgrade
- name: pre-commit autoupdate
run: |
git config --global --add safe.directory '*'
pre-commit autoupdate
- 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 and pre-commit hooks
title: '[bot] Update Python packages and pre-commit hooks'
commit-message: Update Python packages
title: '[bot] Update Python packages'
branch: auto-package-updates
base: master
delete-branch: true
+46 -69
View File
@@ -25,7 +25,7 @@ env:
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 1G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e CI=1 -e PRE_COMMIT_HOME=/tmp/pre-commit -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/pre-commit:/tmp/pre-commit -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
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e CI=1 -e PYTHONWARNINGS=error -e FILEREADER_CACHE=1 -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $BASE_IMAGE /bin/bash -c
PYTEST: pytest --continue-on-collection-errors --cov --cov-report=xml --cov-append --durations=0 --durations-min=5 --hypothesis-seed 0 -n logical
@@ -45,7 +45,6 @@ jobs:
- name: Build devel
timeout-minutes: 1
run: TARGET_DIR=$STRIPPED_DIR release/build_devel.sh
- uses: ./.github/workflows/setup-pre-commit
- uses: ./.github/workflows/setup-with-retry
- name: Check submodules
if: github.ref == 'refs/heads/master' && github.repository == 'commaai/openpilot'
@@ -62,20 +61,22 @@ jobs:
cd $STRIPPED_DIR
${{ env.RUN }} "release/check-dirty.sh && \
MAX_EXAMPLES=5 $PYTEST -m 'not slow' selfdrive/car"
- name: pre-commit
timeout-minutes: 3
- name: static analysis
timeout-minutes: 1
run: |
cd $GITHUB_WORKSPACE
cp .pre-commit-config.yaml $STRIPPED_DIR
cp pyproject.toml $STRIPPED_DIR
cd $STRIPPED_DIR
${{ env.RUN }} "unset PYTHONWARNINGS && SKIP=check-added-large-files,check-hooks-apply,check-useless-excludes pre-commit run --all && chmod -R 777 /tmp/pre-commit"
${{ env.RUN }} "scripts/lint.sh"
build:
strategy:
matrix:
arch: ${{ fromJson('["x86_64"]') }} # TODO: Re-add build test for aarch64 once we switched to ubuntu-2404
runs-on: ubuntu-latest
arch: ${{ fromJson(
((github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && '["x86_64", "aarch64"]' || '["x86_64"]' ) }}
runs-on: ${{ (matrix.arch == 'aarch64') && 'namespace-profile-arm64-2x8' || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v4
with:
@@ -84,7 +85,7 @@ jobs:
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot'
run: |
echo "PUSH_IMAGE=true" >> "$GITHUB_ENV"
: # (TODO: Re-add this once we test other archs) echo "TARGET_ARCHITECTURE=${{ matrix.arch }}" >> "$GITHUB_ENV"
echo "TARGET_ARCHITECTURE=${{ matrix.arch }}" >> "$GITHUB_ENV"
$DOCKER_LOGIN
- uses: ./.github/workflows/setup-with-retry
with:
@@ -93,7 +94,7 @@ jobs:
timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 15 || 30) }} # allow more time when we missed the scons cache
build_mac:
name: build macos
name: build macOS
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
@@ -103,11 +104,36 @@ jobs:
- name: Install dependencies
run: ./tools/mac_setup.sh
env:
SKIP_PROMPT: 1
# package install has DeprecationWarnings
PYTHONWARNINGS: default
- name: Test openpilot environment
run: . .venv/bin/activate && scons -h
- run: echo "CACHE_COMMIT_DATE=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d-%H:%M')" >> $GITHUB_ENV
- name: Getting scons cache
uses: 'actions/cache@v4'
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)
docker_push_multiarch:
name: docker push multiarch tag
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot'
needs: [build]
steps:
- uses: actions/checkout@v4
with:
submodules: false
- name: Setup docker
run: |
$DOCKER_LOGIN
- name: Merge x64 and arm64 tags
run: |
export PUSH_IMAGE=true
scripts/retry.sh selfdrive/test/docker_tag_multiarch.sh base x86_64 aarch64
static_analysis:
name: static analysis
@@ -118,13 +144,12 @@ jobs:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/workflows/setup-pre-commit
- uses: ./.github/workflows/setup-with-retry
- name: Build openpilot
run: ${{ env.RUN }} "scons -j$(nproc)"
- name: pre-commit
timeout-minutes: 4
run: ${{ env.RUN }} "unset PYTHONWARNINGS && pre-commit run --all && chmod -R 777 /tmp/pre-commit"
- name: static analysis
timeout-minutes: 1
run: ${{ env.RUN }} "scripts/lint.sh"
unit_tests:
name: unit tests
@@ -310,8 +335,10 @@ jobs:
})
create_ui_report:
# This job name needs to be the same as UI_JOB_NAME in ui_preview.yaml
name: Create UI Report
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
with:
@@ -328,55 +355,5 @@ jobs:
- name: Upload Test Report
uses: actions/upload-artifact@v4
with:
name: report-${{ inputs.run_number }}
path: selfdrive/ui/tests/test_ui/report_${{ inputs.run_number }}
- name: Get changes to selfdrive/ui
if: ${{ github.event_name == 'pull_request' }}
id: changed-files
uses: tj-actions/changed-files@v44
with:
files: |
selfdrive/ui/**
- name: Checkout ci-artifacts
if: ${{ github.event_name == 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
uses: actions/checkout@v4
with:
repository: commaai/ci-artifacts
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
path: ${{ github.workspace }}/ci-artifacts
ref: master
- name: Push Screenshots
if: ${{ github.event_name == 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
working-directory: ${{ github.workspace }}/ci-artifacts
run: |
git checkout -b openpilot/pr-${{ github.event.pull_request.number }}
git config user.name "GitHub Actions Bot"
git config user.email "<>"
sudo mv ${{ github.workspace }}/selfdrive/ui/tests/test_ui/report/screenshots/* .
git add .
git commit -m "screenshots for PR #${{ github.event.pull_request.number }}"
git push origin openpilot/pr-${{ github.event.pull_request.number }} --force
- name: Comment Screenshots on PR
if: ${{ github.event_name == 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
uses: thollander/actions-comment-pull-request@v2
with:
message: |
<!-- _(run_id_screenshots **${{ github.run_id }}**)_ -->
## UI Screenshots
<table>
<tr>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/homescreen.png"></td>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/onroad.png"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/onroad_map.png"></td>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/onroad_sidebar.png"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/settings_network.png"></td>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/settings_device.png"></td>
</tr>
</table>
comment_tag: run_id_screenshots
pr_number: ${{ github.event.pull_request.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name: report-${{ github.event.number }}
path: selfdrive/ui/tests/test_ui/report_1/screenshots
@@ -1,12 +0,0 @@
name: 'set up pre-commit environment'
runs:
using: "composite"
steps:
- uses: ./.github/workflows/auto-cache
with:
path: .ci_cache/pre-commit
key: pre-commit-${{ hashFiles('**/.pre-commit-config.yaml') }}
restore-keys: |
pre-commit-
save: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot' }}
+2 -2
View File
@@ -5,8 +5,8 @@ on:
workflow_dispatch:
env:
DAYS_BEFORE_PR_CLOSE: 3
DAYS_BEFORE_PR_STALE: 14
DAYS_BEFORE_PR_CLOSE: 2
DAYS_BEFORE_PR_STALE: 9
jobs:
stale:
+1 -7
View File
@@ -21,7 +21,7 @@ env:
BUILD: selfdrive/test/docker_build.sh base
RUN: docker run --shm-size 1G -v $GITHUB_WORKSPACE:/tmp/openpilot -w /tmp/openpilot -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
RUN: docker run --shm-size 2G -v $GITHUB_WORKSPACE:/tmp/openpilot -w /tmp/openpilot -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:
@@ -74,12 +74,6 @@ jobs:
scons-${{ runner.arch }}-ubuntu2004
- name: Building openpilot
run: uv run scons -u -j$(nproc)
- name: Saving scons cache
uses: actions/cache/save@v4
if: github.ref == 'refs/heads/master'
with:
path: /tmp/scons_cache
key: scons-${{ runner.arch }}-ubuntu2004-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
devcontainer:
name: devcontainer
+91
View File
@@ -0,0 +1,91 @@
name: "ui preview"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened, edited]
branches:
- 'master'
paths:
- 'selfdrive/ui/**'
env:
UI_JOB_NAME: "Create UI Report"
jobs:
preview:
if: github.repository == 'commaai/openpilot'
name: preview
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: write
actions: read
steps:
- name: Waiting for ui test to start
run: sleep 30
- name: Wait for ui report
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: ${{ env.UI_JOB_NAME }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
allowed-conclusions: success
wait-interval: 20
- name: Get workflow run ID
id: get_run_id
run: |
echo "run_id=$(curl https://api.github.com/repos/${{ github.repository }}/commits/${{ github.event.pull_request.head.sha }}/check-runs | jq -r '.check_runs[] | select(.name == "${{ env.UI_JOB_NAME }}") | .html_url | capture("(?<number>[0-9]+)") | .number')" >> $GITHUB_OUTPUT
- name: Checkout ci-artifacts
uses: actions/checkout@v4
with:
repository: commaai/ci-artifacts
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
path: ${{ github.workspace }}/ci-artifacts
ref: master
- name: Download artifact
id: download-artifact
uses: dawidd6/action-download-artifact@v6
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
run_id: ${{ steps.get_run_id.outputs.run_id }}
search_artifacts: true
name: report-${{ github.event.number }}
path: ${{ github.workspace }}/ci-artifacts
- name: Push Screenshots
working-directory: ${{ github.workspace }}/ci-artifacts
run: |
git checkout -b openpilot/pr-${{ github.event.number }}
git config user.name "GitHub Actions Bot"
git config user.email "<>"
git add ${{ github.workspace }}/ci-artifacts/*
git commit -m "screenshots for PR #${{ github.event.number }}"
git push origin openpilot/pr-${{ github.event.number }} --force
- name: Comment Screenshots on PR
uses: thollander/actions-comment-pull-request@v2
with:
message: |
<!-- _(run_id_screenshots **${{ github.run_id }}**)_ -->
## UI Screenshots
<table>
<tr>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.number }}/homescreen.png"></td>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.number }}/onroad.png"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.number }}/onroad_map.png"></td>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.number }}/onroad_sidebar.png"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.number }}/settings_network.png"></td>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.number }}/settings_device.png"></td>
</tr>
</table>
comment_tag: run_id_screenshots
pr_number: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+3 -1
View File
@@ -14,6 +14,8 @@ model2.png
a.out
.hypothesis
/docs_site/
*.dylib
*.DSYM
*.d
@@ -103,4 +105,4 @@ Pipfile
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide
.ionide
+32 -48
View File
@@ -9,6 +9,10 @@ variables:
GIT_CONFIG_USER_EMAIL: "gitlab@pipeline.com"
GIT_CONFIG_USER_NAME: "Gitlab Pipeline"
PUBLIC_REPO_URL: "https://github.com/sunnyhaibin/sunnypilot"
BASE_BUILD_NUMER: 3000
EXTRA_VERSION_IDENTIFIER: "${CI_PIPELINE_IID}"
NEW_BRANCH: ${CI_COMMIT_REF_NAME}-prebuilt
stages:
- build
@@ -23,44 +27,43 @@ default:
- x86
.default_before_script: &default_before_script
- 'export VERSION=$(eval $VERSION)${EXTRA_VERSION_IDENTIFIER}'
- 'if [ "$EXTRA_VERSION_IDENTIFIER" = "$CI_PIPELINE_IID" ]; then export EXTRA_VERSION_IDENTIFIER=$((CI_PIPELINE_IID + BASE_BUILD_NUMER)); fi'
- 'export VERSION=$(eval $VERSION)-${EXTRA_VERSION_IDENTIFIER}'
- 'mkdir -p "${BUILD_DIR}/"'
- 'git config --global user.email "${GIT_CONFIG_USER_EMAIL}"'
- 'git config --global user.name "${GIT_CONFIG_USER_NAME}"'
workflow: # If running on any branch other than main, use the `aws-datacontracts-dev` account; otherwise use `aws-datacontracts`
workflow: # If running on any branch other than main.
rules:
# We are an MR, but it's a draft, we won't proceed with anything.
- if: '$CI_MERGE_REQUEST_TITLE =~ /^wip:/i || $CI_MERGE_REQUEST_TITLE =~ /^draft:/i'
when: never
# We are a merge request
- if: $CI_MERGE_REQUEST_IID #|| $CI_COMMIT_REF_NAME == "gitlab-pipelines" # TBD once merged
variables:
EXTRA_VERSION_IDENTIFIER: "-${CI_PIPELINE_IID}"
NEW_BRANCH: ${CI_COMMIT_REF_NAME}-prebuilt
when: always
# Below are the rules when a commit is done (code has been added to the branch)
# Commit to master-dev-c3
- if: $CI_COMMIT_REF_NAME == $DEV_C3_SOURCE_BRANCH
variables:
EXTRA_VERSION_IDENTIFIER: "-${CI_PIPELINE_IID}"
EXTRA_VERSION_IDENTIFIER: "${CI_PIPELINE_IID}"
NEW_BRANCH: "dev-c3"
AUTO_BUILD: true
when: always
#commit made to main (master)
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
variables:
NEW_BRANCH: "staging-c3"
VERSION: 'cat common/version.h | grep COMMA_VERSION | sed -e "s/[^0-9|.]//g"'
EXTRA_VERSION_IDENTIFIER: "-staging"
EXTRA_VERSION_IDENTIFIER: "staging"
AUTO_PUBLISH: true
AUTO_BUILD: true
when: always
# if tag
- if: $CI_COMMIT_TAG
variables:
NEW_BRANCH: "release-c3"
VERSION: 'cat common/version.h | grep COMMA_VERSION | sed -e "s/[^0-9|.]//g"'
EXTRA_VERSION_IDENTIFIER: "-release"
EXTRA_VERSION_IDENTIFIER: "release"
AUTO_BUILD: true
- when: always
@@ -92,7 +95,7 @@ build:
- sed -i '/from .board.jungle import PandaJungle, PandaJungleDFU/s/^/#/' panda/__init__.py # comment panda jungle when prebuilt
- scons -j$(nproc) cache_dir=${CI_DIR}/scons_cache --minimal
- touch ${BUILD_DIR}/prebuilt
- sudo rm -rf ${OUTPUT_DIR}
- sudo rm -rf ${OUTPUT_DIR}
- mkdir -p ${OUTPUT_DIR}
# We first include the paths we want to keep, even if we later will be excluding the other things on those paths
- rsync -avm
@@ -129,43 +132,22 @@ build:
--exclude='**/selfdrive/ui/**/*.h'
--exclude='**/selfdrive/ui/qt/offroad/sunnypilot/'
--exclude='**/.git/'
--exclude='**/SConstruct'
--exclude='**/SConscript'
--delete-excluded
--chown=comma:comma
${BUILD_DIR}/ ${OUTPUT_DIR}/
after_script:
# cleanup build dir after doing work
# cleanup build dir after doing work
- find $BUILD_DIR/ -mindepth 1 -delete
artifacts:
paths:
- ${OUTPUT_DIR}/
tags: [ 'sunnypilot', 'tici' ]
rules:
- if: $CI_MERGE_REQUEST_IID
when: manual
- if: $NEW_BRANCH
- if: $AUTO_BUILD
when: always
check no source code sent:
image: alpine
stage: sanity
variables:
FORBIDDEN_FILE_EXTENSIONS: "*.a,*.o,*.os,*.pyc,moc_*,*.cc,Jenkinsfile,supercombo.onnx,.sconsign.dblite"
FORBIDDEN_DIR_PATTERNS: "*panda/certs,*panda/crypto,*release,*.github,*selfdrive/ui/replay,*__pycache__"
REQUIRED_FILE_EXTENSIONS: "*.py,*.json"
REQUIRED_DIR_PATTERNS: "*selfdrive/ui,*openpilot"
before_script:
- apk update && apk upgrade
- apk add bash findutils
script:
- cd ${OUTPUT_DIR}
- echo "Checking that we have properly cleaned up"
- ${CI_DIR}/sanity_check.sh "$FORBIDDEN_FILE_EXTENSIONS" "$FORBIDDEN_DIR_PATTERNS" true
- echo "Checking that our sanity check works and also checking that some required files are indeed found"
- ${CI_DIR}/sanity_check.sh "$REQUIRED_FILE_EXTENSIONS" "$REQUIRED_DIR_PATTERNS" false
rules:
- if: $NEW_BRANCH
when: on_success
- when: never
- when: manual
.publish_base: &publish_base
image: alpine
@@ -175,9 +157,6 @@ check no source code sent:
needs:
- job: build
artifacts: true
- job: "check no source code sent"
artifacts: false
optional: false
before_script:
- 'apk update && apk upgrade'
- 'apk add git bash openssh'
@@ -194,17 +173,19 @@ check no source code sent:
- echo "${GIT_ORIGIN}"
- echo "Calling to publish [${CI_DIR}/publish.sh ${CI_PROJECT_DIR} ${OUTPUT_DIR} ${NEW_BRANCH} ${VERSION} ${GIT_ORIGIN}]"
- git config --global --add safe.directory ${OUTPUT_DIR}
- $CI_DIR/publish.sh "${CI_PROJECT_DIR}" "${OUTPUT_DIR}" "${NEW_BRANCH}" "${VERSION}" "${GIT_ORIGIN}" "${EXTRA_VERSION_IDENTIFIER}"
- $CI_DIR/publish.sh "${CI_PROJECT_DIR}" "${OUTPUT_DIR}" "${NEW_BRANCH}" "${VERSION}" "${GIT_ORIGIN}" "-${EXTRA_VERSION_IDENTIFIER}"
allow_failure: false
publish to private gitlab prebuilt:
extends: ".publish_base"
variables:
GIT_ORIGIN: git@gitlab.com:sunnypilot/public/sunnypilot.git
GIT_ORIGIN: git@gitlab.com:sunnypilot/public/sunnypilot-prebuilts.git
rules:
- if: $NEW_BRANCH
- if: $AUTO_BUILD
when: on_success
- when: never
- if: $CI_MERGE_REQUEST_IID
when: on_success
- when: manual
publish to public github prebuilt:
extends: ".publish_base"
@@ -213,9 +194,9 @@ publish to public github prebuilt:
GIT_CONFIG_USER_EMAIL: "jason.wen@sunnypilot.ai"
GIT_CONFIG_USER_NAME: "Jason Wen"
rules:
- if: $NEW_BRANCH
when: manual
- when: never
- if: $AUTO_PUBLISH
when: on_success
- when: manual
.notify_discord: &notify_discord
image: alpine
@@ -249,6 +230,9 @@ notify new dev build:
needs: ["publish to public github prebuilt"] # This notify shall only happen after a publish to github public
variables:
TEMPLATE: "discord_template_notify_dev_public.json"
before_script:
- !reference [".notify_discord", "before_script"]
- export EXTRA_VERSION_IDENTIFIER=$((CI_PIPELINE_IID + BASE_BUILD_NUMER))
rules:
- if: $NEW_BRANCH == "dev-c3"
variables:
+5 -8
View File
@@ -1,21 +1,18 @@
[submodule "panda"]
path = panda
url = ../../sunnyhaibin/panda-special.git
url = https://github.com/sunnyhaibin/panda.git
[submodule "opendbc"]
path = opendbc
url = https://github.com/sunnyhaibin/opendbc.git
path = opendbc_repo
url = https://github.com/sunnypilot/opendbc.git
[submodule "msgq"]
path = msgq_repo
url = https://github.com/commaai/msgq.git
url = https://github.com/sunnypilot/msgq.git
[submodule "rednose_repo"]
path = rednose_repo
url = https://github.com/commaai/rednose.git
[submodule "body"]
path = body
url = https://github.com/commaai/body.git
[submodule "teleoprtc_repo"]
path = teleoprtc_repo
url = https://github.com/commaai/teleoprtc
[submodule "tinygrad"]
path = tinygrad_repo
url = https://github.com/geohot/tinygrad.git
url = https://github.com/tinygrad/tinygrad.git
+41
View File
@@ -0,0 +1,41 @@
[importlinter]
root_packages =
openpilot
[importlinter:contract:1]
name = Forbid imports from openpilot.selfdrive.car to openpilot.system
type = forbidden
source_modules =
openpilot.selfdrive.car
forbidden_modules =
openpilot.system
openpilot.body
openpilot.docs
openpilot.msgq
openpilot.panda
openpilot.rednose
openpilot.release
openpilot.teleoprtc
openpilot.tinygrad
ignore_imports =
openpilot.selfdrive.car.card -> openpilot.common.realtime
openpilot.selfdrive.car.card -> openpilot.selfdrive.controls.lib.events
openpilot.selfdrive.car.interfaces -> openpilot.selfdrive.controls.lib.events
openpilot.selfdrive.car.tests.test_models -> openpilot.tools.lib.logreader
openpilot.selfdrive.car.tests.test_models -> openpilot.selfdrive.car.card
openpilot.selfdrive.car.tests.test_models -> openpilot.tools.lib.route
openpilot.selfdrive.car.tests.test_models -> openpilot.system.hardware.hw
openpilot.selfdrive.car.tests.test_models -> openpilot.selfdrive.test.helpers
openpilot.selfdrive.car.isotp_parallel_query -> openpilot.common.swaglog
openpilot.selfdrive.car.fw_versions -> openpilot.common.swaglog
openpilot.selfdrive.car.disable_ecu -> openpilot.common.swaglog
openpilot.selfdrive.car.vin -> openpilot.common.swaglog
openpilot.selfdrive.car.ecu_addrs -> openpilot.common.swaglog
openpilot.selfdrive.car.car_helpers -> openpilot.common.swaglog
openpilot.selfdrive.car.car_helpers -> openpilot.system.version
openpilot.selfdrive.car.interfaces -> openpilot.selfdrive.controls.lib.drive_helpers
openpilot.selfdrive.car.tests.test_car_interfaces -> openpilot.selfdrive.controls.lib.latcontrol_angle
openpilot.selfdrive.car.tests.test_car_interfaces -> openpilot.selfdrive.controls.lib.longcontrol
openpilot.selfdrive.car.tests.test_car_interfaces -> openpilot.selfdrive.controls.lib.latcontrol_torque
openpilot.selfdrive.car.tests.test_car_interfaces -> openpilot.selfdrive.controls.lib.latcontrol_pid
unmatched_ignore_imports_alerting = warn
-98
View File
@@ -1,98 +0,0 @@
exclude: '^(tinygrad_repo)'
repos:
- repo: meta
hooks:
- id: check-hooks-apply
- id: check-useless-excludes
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: check-ast
exclude: '^(third_party)/'
- id: check-json
exclude: '.devcontainer/devcontainer.json|.vscode/' # these support JSON with comments
- id: check-toml
- id: check-xml
- id: check-yaml
- id: check-merge-conflict
- id: check-symlinks
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
- id: check-added-large-files
exclude: '(docs/CARS.md)|(uv.lock)|(third_party/acados/include/blasfeo/include/blasfeo_d_kernel.h)'
args:
- --maxkb=120
- --enforce-all
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
hooks:
- id: codespell
exclude: '^(third_party/)|(body/)|(msgq/)|(panda/)|(opendbc/)|(rednose/)|(rednose_repo/)|(teleoprtc/)|(teleoprtc_repo/)|(selfdrive/ui/translations/.*.ts)|(uv.lock)'
args:
# if you've got a short variable name that's getting flagged, add it here
- -L bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn
- --builtins clear,rare,informal,usage,code,names,en-GB_to_en-US
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.0
hooks:
- id: ruff
exclude: '^(third_party/)|(msgq/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)'
- repo: local
hooks:
- id: mypy
name: mypy
entry: mypy
language: system
types: [python]
args:
- --local-partial-types
- --explicit-package-bases
exclude: '^(third_party/)|(body/)|(msgq/)|(opendbc/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)'
- repo: local
hooks:
- id: cppcheck
name: cppcheck
entry: cppcheck
language: system
types: [c++]
exclude: '^(third_party/)|(msgq/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(tools/)|(selfdrive/modeld/thneed/debug/)|(selfdrive/modeld/test/)|(selfdrive/camerad/test/)|(installer/)'
args:
- --error-exitcode=1
- --language=c++
- --quiet
- --force
- -j8
- --library=qt
- --include=third_party/kaitai/kaitaistream.h
- repo: https://github.com/cpplint/cpplint
rev: 1.6.1
hooks:
- id: cpplint
exclude: '^(third_party/)|(msgq/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(generated/)'
args:
- --quiet
- --counting=total
- --linelength=240
# https://google.github.io/styleguide/cppguide.html
# relevant rules are whitelisted, see all options with: cpplint --filter=
- --filter=-build,-legal,-readability,-runtime,-whitespace,+build/include_subdir,+build/forward_decl,+build/include_what_you_use,+build/deprecated,+whitespace/comma,+whitespace/line_length,+whitespace/empty_if_body,+whitespace/empty_loop_body,+whitespace/empty_conditional_body,+whitespace/forcolon,+whitespace/parens,+whitespace/semicolon,+whitespace/tab,+readability/braces
- repo: https://github.com/MarcoGorelli/cython-lint
rev: v0.16.2
hooks:
- id: cython-lint
exclude: '^(third_party/)|(msgq/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(generated/)'
args:
- --max-line-length=240
- --ignore=E111, E302, E305
- repo: local
hooks:
- id: test_translations
name: test translations
entry: pytest selfdrive/ui/tests/test_translations.py
language: system
pass_filenames: false
files: '^selfdrive/ui/translations/'
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.28.6
hooks:
- id: check-github-workflows
+5 -3
View File
@@ -36,14 +36,16 @@ sunnypilot - 0.9.8.0 (2024-xx-xx)
* In response to the official deprecation of support for Smart DSU (SDSU) and Radar CAN Filter in the upstream ([commaai/openpilot#32777](https://github.com/commaai/openpilot/pull/32777)), sunnypilot will continue maintaining software support for Smart DSU (SDSU) and Radar CAN Filter
* UPDATED: Continued support for Mapbox navigation
* In response to the official temporary deprecation of support for Mapbox navigation in the upstream ([commaai/openpilot#32773](https://github.com/commaai/openpilot/pull/32773)), sunnypilot will continue maintaining software support for Mapbox navigation
* NEW❗: Toyota - Automatic Brake Hold (AHB) thanks to AlexandreSato!
* When you stop the vehicle completely by depressing the brake pedal, sunnypilot will activate Auto Brake Hold
* NOTE: Only for Toyota/Lexus vehicles with TSS2/LSS2
* NEW❗: Toyota - Automatic Door Locking and Unlocking thanks to AlexandreSato, cydia2020, and dragonpilot-community!
* Auto Lock by Speed: All doors are automatically locked when vehicle speed is approximately 6 mph (10 km/h) or higher
* Auto Unlock by Shift to P: All doors are automatically unlocked when shifting the shift lever to P
* FIXED: Driving Personality:
* Maniac mode now correctly enforced when selected
* UI Updates
* Display Metrics Below Chevron
* NEW❗: Time to Lead Car
* Displays the time to reach the position previously occupied by the lead car
* NEW❗: Display Distance, Speed, and Time to Lead Car simultaneously
* Kia Ceed Plug-in Hybrid Non-SCC 2022 support thanks to TerminatorNL!
sunnypilot - 0.9.7.1 (2024-06-13)
+77
View File
@@ -0,0 +1,77 @@
# How Tos
This page is a repository of useful how-tos as a supplement for additional information.
Table of Contents
=======================
* [Radar Tracks](#Radar-Tracks)
* [Enable Radar Tracks](#-Enable-Radar-Tracks)
* [Enable Mapbox Navigation](#-Enable-Mapbox-Navigation)
---
<details><summary><h3>📡 Radar Tracks</h3></summary>
Radar tracks can now be enabled manually on applicable cars through SSH thanks to [@greghogan](https://github.com/greghogan) and [@pd0wm](https://github.com/pd0wm).
Some Hyundai radars can be reconfigured to output (debug) radar points on bus 1.
Reconfiguration is done over UDS by reading/writing to 0x0142 using the Read/Write Data By Identifier
endpoints (0x22 & 0x2E). This script checks your radar firmware version against a list of known
firmware versions. If you want to try on a new radar, make sure to note the default config value
in case it is different from the other radars and you need to revert the changes.
After changing the config the car should not show any faults when openpilot is not running.
These config changes are persistent across car reboots. You need to run this script again
to go back to the default values.
**USE AT YOUR OWN RISK!** Stock system safety features, like AEB and FCW, might be affected by these changes.
**How radar points can be used along with vision:**
* Current OP long policy is identify with vision first, if vision sees a vehicle match it to a radar point. If vision sees nothing you get a false negative and no lead car detection. (Source: [Hubblesphere#7894 from comma.ai community Discord](https://discord.com/channels/469524606043160576/872899198738104330/872913890793635872))
### 🚨 Enable Radar Tracks
***(EXPERIMENTAL, as of January 1st, 2022)***
***(Only applicable to some Hyundai, Kia, and Genesis cars, as of January 1st, 2022)***
*(Base on version 0.8.12 [`devel`](https://github.com/commaai/openpilot/tree/devel))*
**USE AT YOUR OWN RISK!** Stock system safety features, like AEB and FCW, might be affected by these changes.
1. Ensure the car is at the `OFF` ignition position.
2. Connect your compatible comma device (EON, C2, C3) to the car. comma device power should be ON.
3. Use a laptop or applicable device to connect to your comma device via SSH. (Tips: Instructions to SSH in [HERE](https://github.com/commaai/openpilot/wiki/SSH))
4. In the SSH terminal after successfully connected to your comma device, execute the following commands:
1. `pkill -f openpilot`
2. `python /data/openpilot/selfdrive/debug/hyundai_enable_radar_points.py`
3. Follow the instructions in the script:
* `Power on the vehicle keeping the engine off (press start button twice) then type OK to continue`.
* If successful, the following message should appear: `[DONE]. Restart your vehicle and ensure there are no faults`.
* If the script did not run successfully, reach out to the community in [Sunnyhaibin's Openpilot Discord Server](https://discord.gg/wRW3meAgtx) or `#hyundai-kia-genesis channel` on [commaai community Discord Server](https://discord.comma.ai) for assistance.
4. Reboot your comma device:
1. C3: `sudo reboot`
2. C2 or EON: `reboot`
5. Once your comma device is rebooted, start your car with engine on (with or without comma device connected). Ensure that there are no faults from the car. If there are faults, reach out to the community in [Sunnyhaibin's Openpilot Discord Server](https://discord.gg/wRW3meAgtx) or `#hyundai-kia-genesis channel` on [commaai community Discord Server](https://discord.comma.ai) for assistance.
6. Go for a quick drive and drive behind a lead car with varied follow distance. Then, come back and allow the drive to upload its `rlogs` in [comma Connect](https://connect.comma.ai).
7. With all `rlogs` uploaded, open the drive in Cabana from [comma Connect](https://connect.comma.ai). Load DBC -> `hyundai_kia_mando_front_radar.dbc`, then search `RADAR_TRACK_50x` (`x` could be anything), open any of them, and look at `LONG_DIST`.
8. If the radar tracks data is relevant with the lead car you drove behind, you are done! Your car now have radar tracks enabled.
</details>
<details><summary><h3>🗺 Enable Mapbox Navigation</h3></summary>
1) Create a free mapbox account. Account will ask for a credit card for verification. You will not be charged for the free tier.
2) On the Dashboard, you will see a section called Access Tokens. Click `Create a Token`. Name it whatever you like. Set the scopes to allow everything for both Public and Secret. Copy both of these keys. **YOU WON'T BE ABLE TO ACCESS THE SECRET KEY AFTER THIS WINDOW.**
3) Once rebooted, connect your C3 to a network with internet access and find the C3s IP address.
4) In a browser, navigate to that IP with **port 8082** (i.e 192.168.1.69:8082). You should be greeted with the Comma logo and a public key input field.
5) Paste your Public token (pk.xx), click enter, paste your Secret key (sk.xx), click enter. You can now search for places. This page will be available at your devicess IP address/port 8082 to search for destinations.
6) To set Home and Work addresses, search for a place, select Home/Work from the dropdown and click Navigate. For non-Home/Work destinations, select Recent Places.<br>*At this time, it is not possible to search directly on the C3.*
**TIPS:**
- If your C3 is showing a black screen that says “Map Loading”, performing a reboot via the UI should fix it.
- If your phone can create a Hotspot, you are able to connect the C3 to your phone hotspot and use your phone browser to search for places.
- In the Navigation panel on the C3, you can select Home, Work, and from a list of Recent Places you have navigated to without needing a browser (assuming the C3 is connected to the internet.)
**IMPORTANT NOTE:** Your C3 will require an active internet connection to download map data, generate driving directions, and ETA. Once map data and directions are downloaded, it *is* possible to use it offline, however nothing will update (such as new driving direction after a missed turn, updated ETA, map data further into your drive etc.)
***NAVIGATION NOTE:** At this time, mapbox does not support alphanumeric addresses (i.e W123N1234 Main St). There is currently no known workaround for this.*
</details>
Vendored
+1 -1
View File
@@ -83,7 +83,7 @@ def deviceStage(String stageName, String deviceType, List extra_env, def steps)
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: 20, unit: 'MINUTES') {
timeout(time: 35, unit: 'MINUTES') {
retry (3) {
device(device_ip, "git checkout", extra + "\n" + readFile("selfdrive/test/setup_device_ci.sh"))
}
+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
+12 -41
View File
@@ -48,7 +48,6 @@ Join the official sunnypilot Discord server to stay up to date with all the late
To use sunnypilot in a car, you need the following:
* A supported device to run this software
* a [comma three](https://comma.ai/shop/products/three), or
* a comma two (only with older versions below 0.8.13)
* This software
* One of [the 250+ supported cars](https://github.com/commaai/openpilot/blob/master/docs/CARS.md). We support Honda, Toyota, Hyundai, Nissan, Kia, Chrysler, Lexus, Acura, Audi, VW, Ford and more. If your car is not supported but has adaptive cruise control and lane-keeping assist, it's likely able to run sunnypilot.
* A [car harness](https://comma.ai/shop/products/car-harness) to connect to your car
@@ -115,40 +114,12 @@ Please refer to [Recommended Branches](#-recommended-branches) to find your pref
Requires further assistance with software installation? Join the [sunnypilot Discord server](https://discord.sunnypilot.com) and message us in the `#installation-help` channel.
comma two
------
1. [Factory reset/uninstall](https://github.com/commaai/openpilot/wiki/FAQ#how-can-i-reset-the-device) the previous software if you have another software/fork installed.
2. After factory reset/uninstall and upon reboot, select `Custom Software` when given the option.
3. Input the installation URL per [Recommended Branches](#-recommended-branches). Example: ```https://smiskol.com/fork/sunnyhaibin/0.8.12-4-prod```
4. Complete the rest of the installation following the onscreen instructions.
Requires further assistance with software installation? Join the [sunnypilot Discord server](https://discord.sunnypilot.com) and message us in the `#installation-help` channel.
</details>
<details>
<summary>SSH (More Versatile)</summary>
<br>
Prerequisites: [How to SSH](https://github.com/commaai/openpilot/wiki/SSH)
If you are looking to install sunnypilot via SSH, run the following command in an SSH terminal after connecting to your device:
comma three:
------
* [`release-c3`](https://github.com/sunnyhaibin/openpilot/tree/release-c3):
```
cd /data; rm -rf ./openpilot; git clone -b release-c3 --recurse-submodules https://github.com/sunnyhaibin/sunnypilot.git openpilot; cd openpilot; sudo reboot
```
comma two:
------
* [`0.8.12-prod-personal-hkg`](https://github.com/sunnyhaibin/openpilot/tree/0.8.12-prod-personal-hkg):
```
cd /data; rm -rf ./openpilot; git clone -b 0.8.12-prod-personal-hkg --recurse-submodules https://github.com/sunnyhaibin/sunnypilot.git openpilot; cd openpilot; sudo reboot
cd /data && rm -rf ./openpilot && git clone -b release-c3 --recurse-submodules https://github.com/sunnyhaibin/sunnypilot.git openpilot && cd openpilot && sudo reboot
```
After running the command to install the desired branch, your comma device should reboot.
@@ -170,16 +141,16 @@ After running the command to install the desired branch, your comma device shoul
* Speed Limit Control (SLC) - Set speed limit based on map data or car interface (if applicable)
* HKG only: Highway Driving Assist (HDA) status integration - Use cars native speed sign detection to set desired speed (on applicable HKG cars only)
- [**Gap Adjust Cruise (GAC)**](#gap-adjust-cruise) - Allow `GAP`/`INTERVAL`/`DISTANCE` button on the steering wheel or on-screen button to adjust the follow distance from the lead car. See table below for options
- [**Quiet Drive 🤫**](#-quiet-drive) - Toggle to mute all notification sounds (excluding driver safety warnings)
- [**Auto Lane Change Timer**](#Auto-Lane-Change-Timer) - Set a timer to delay the auto lane change operation when the blinker is used. No nudge on the steering wheel is required to auto lane change if a timer is set
- [**Force Car Recognition (FCR)**](#Force-Car-Recognition-) - Use a selector to force your car to be recognized by sunnypilot
- [**Fix sunnypilot No Offroad**](#Fix-sunnypilot-No-Offroad) - Enforce sunnypilot to go offroad and turns off after shutting down the car. This feature fixes non-official devices running sunnypilot without comma power
- [**Enable ACC+MADS with RES+/SET-**](#Enable-ACC+MADS-with-RES+/SET-) - Engage both ACC and MADS with a single press of RES+ or SET- button
- [**Offline OSM Maps**](#Offline-OSM-Maps) - OSM database can now be downloaded locally for offline use[^2]. This enables offline SLC, V-TSC and M-TSC. Currently available for US South, US West, US Northeast, Florida, Taiwan, South Africa and New Zealand
- [**Various Live Tuning**](#Various-Live-Tuning) - Ability to tailor your driving experience on the fly:
* Enforce Torque Lateral Control - Use the newest [torque controller](https://blog.comma.ai/0815release/#torque-controller) for all vehicles.
* Torque Lateral Control Live Tune - Ability to adjust the torque controllers `FRICTION` and `LAT_ACCEL_FACTOR` values to suit your vehicle.
* Torque Lateral Controller Self-Tune - Enable automatic turning for the Torque controller.
- [**Quiet Drive 🤫**](#-quiet-drive) - Toggle to mute all notification sounds (excluding driver safety warnings)
- [**Auto Lane Change Timer**](#Auto-Lane-Change-Timer) - Set a timer to delay the auto lane change operation when the blinker is used. No nudge on the steering wheel is required to auto lane change if a timer is set
- [**Force Car Recognition (FCR)**](#Force-Car-Recognition-) - Use a selector to force your car to be recognized by sunnypilot
- [**Fix sunnypilot No Offroad**](#Fix-sunnypilot-No-Offroad) - Enforce sunnypilot to go offroad and turns off after shutting down the car. This feature fixes non-official devices running sunnypilot without comma power
- [**Enable ACC+MADS with RES+/SET-**](#Enable-ACC+MADS-with-RES+/SET-) - Engage both ACC and MADS with a single press of RES+ or SET- button
- [**Offline OSM Maps**](#Offline-OSM-Maps) - OSM database can now be downloaded locally for offline use[^2]. This enables offline SLC, V-TSC and M-TSC. Currently available for US South, US West, US Northeast, Florida, Taiwan, South Africa and New Zealand
- [**Various Live Tuning**](#Various-Live-Tuning) - Ability to tailor your driving experience on the fly:
* Enforce Torque Lateral Control - Use the newest [torque controller](https://blog.comma.ai/0815release/#torque-controller) for all vehicles.
* Torque Lateral Control Live Tune - Ability to adjust the torque controllers `FRICTION` and `LAT_ACCEL_FACTOR` values to suit your vehicle.
* Torque Lateral Controller Self-Tune - Enable automatic turning for the Torque controller.
### Visual Enhancements
* **M.A.D.S Status Icon** - Dedicated icon to display M.A.D.S. engagement status
@@ -355,7 +326,7 @@ Example:
---
How-To instructions can be found in [HOW-TOS.md](https://github.com/sunnyhaibin/openpilot/blob/(!)README/HOW-TOS.md).
How-To instructions can be found in [HOW-TOS.md](HOW-TOS.md).
</details>
+14 -7
View File
@@ -72,6 +72,12 @@ AddOption('--minimal',
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('--stock-ui',
action='store_true',
dest='stock_ui',
default=False,
help='Build stock UI instead of sunnypilot UI')
## Architecture name breakdown (arch)
## - larch64: linux tici aarch64
## - aarch64: linux pc aarch64
@@ -104,7 +110,6 @@ if arch == "larch64":
libpath = [
"/usr/local/lib",
"/usr/lib",
"/system/vendor/lib64",
f"#third_party/acados/{arch}/lib",
]
@@ -172,9 +177,12 @@ if arch != "Darwin":
ldflags += ["-Wl,--as-needed", "-Wl,--no-undefined"]
# Enable swaglog include in submodules
cflags += ['-DSWAGLOG="\\"common/swaglog.h\\""']
cxxflags += ['-DSWAGLOG="\\"common/swaglog.h\\""']
if not GetOption('stock_ui'):
cflags += ["-DSUNNYPILOT"]
cxxflags += ["-DSUNNYPILOT"]
ccflags_option = GetOption('ccflags')
if ccflags_option:
ccflags += ccflags_option.split(' ')
@@ -208,7 +216,6 @@ env = Environment(
"#third_party/json11",
"#third_party/linux/include",
"#third_party/snpe/include",
"#third_party/qrcode",
"#third_party",
"#cereal",
"#msgq",
@@ -236,7 +243,7 @@ env = Environment(
COMPILATIONDB_USE_ABSPATH=True,
REDNOSE_ROOT="#",
tools=["default", "cython", "compilation_db", "rednose_filter"],
toolpath=["#rednose_repo/site_scons/site_tools"],
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
)
if arch == "Darwin":
@@ -276,7 +283,8 @@ if arch == "Darwin":
else:
envCython["LINKFLAGS"] = ["-pthread", "-shared"]
Export('envCython')
np_version = SCons.Script.Value(np.__version__)
Export('envCython', 'np_version')
# Qt build environment
qt_env = env.Clone()
@@ -320,7 +328,7 @@ try:
except SCons.Errors.UserError:
qt_env.Tool('qt')
qt_env['CPPPATH'] += qt_dirs# + ["#selfdrive/ui/qt/"]
qt_env['CPPPATH'] += qt_dirs + ["#third_party/qrcode"]
qt_flags = [
"-D_REENTRANT",
"-DQT_NO_DEBUG",
@@ -369,7 +377,6 @@ Export('messaging')
# Build other submodules
SConscript([
'body/board/SConscript',
'opendbc/can/SConscript',
'panda/SConscript',
])
Submodule body deleted from 0e74db67ae
-1
View File
@@ -137,7 +137,6 @@ struct CarEvent @0x9b1657f34caf3ad3 {
speedLimitPreActive @139;
speedLimitConfirmed @140;
torqueNNLoad @141;
spAutoBrakeHold @142;
radarCanErrorDEPRECATED @15;
communityFeatureDisallowedDEPRECATED @62;
+36 -4
View File
@@ -137,8 +137,6 @@ struct FrameData {
requestId @28 :UInt32;
encodeId @1 :UInt32;
frameType @7 :FrameType;
# Timestamps
timestampEof @2 :UInt64;
timestampSof @8 :UInt64;
@@ -158,7 +156,7 @@ struct FrameData {
temperaturesC @24 :List(Float32);
enum FrameType {
enum FrameTypeDEPRECATED {
unknown @0;
neo @1;
chffrAndroid @2;
@@ -175,6 +173,7 @@ struct FrameData {
frameLengthDEPRECATED @3 :Int32;
globalGainDEPRECATED @5 :Int32;
frameTypeDEPRECATED @7 :FrameTypeDEPRECATED;
androidCaptureResultDEPRECATED @9 :AndroidCaptureResult;
lensPosDEPRECATED @11 :Int32;
lensSagDEPRECATED @12 :Float32;
@@ -337,9 +336,9 @@ enum LaneChangeDirection {
struct CanData {
address @0 :UInt32;
busTime @1 :UInt16;
dat @2 :Data;
src @3 :UInt8;
busTimeDEPRECATED @1 :UInt16;
}
struct DeviceState @0xa4d8b5af2aa492eb {
@@ -1252,6 +1251,38 @@ struct LiveLocationKalman {
}
}
struct LivePose {
# More info on reference frames:
# https://github.com/commaai/openpilot/tree/master/common/transformations
orientationNED @0 :XYZMeasurement;
velocityDevice @1 :XYZMeasurement;
accelerationDevice @2 :XYZMeasurement;
angularVelocityDevice @3 :XYZMeasurement;
inputsOK @4 :Bool = false;
posenetOK @5 :Bool = false;
sensorsOK @6 :Bool = false;
filterState @7 :FilterState;
struct XYZMeasurement {
x @0 :Float32;
y @1 :Float32;
z @2 :Float32;
xStd @3 :Float32;
yStd @4 :Float32;
zStd @5 :Float32;
valid @6 :Bool;
}
struct FilterState {
value @0 : List(Float64);
std @1 : List(Float64);
valid @2 : Bool;
}
}
struct ProcLog {
cpuTimes @0 :List(CPUTimes);
mem @1 :Mem;
@@ -2293,6 +2324,7 @@ struct Event {
carParams @69: Car.CarParams;
driverMonitoringState @71: DriverMonitoringState;
liveLocationKalman @72 :LiveLocationKalman;
livePose @129 :LivePose;
modelV2 @75 :ModelDataV2;
drivingModelData @128 :DrivingModelData;
driverStateV2 @92 :DriverStateV2;
+8 -3
View File
@@ -2,7 +2,8 @@
from msgq.ipc_pyx import Context, Poller, SubSocket, PubSocket, SocketEventHandle, toggle_fake_events, \
set_fake_prefix, get_fake_prefix, delete_fake_prefix, wait_for_one_event
from msgq.ipc_pyx import MultiplePublishersError, IpcError
from msgq import fake_event_handle, pub_sock, sub_sock, drain_sock_raw, context
from msgq import fake_event_handle, pub_sock, sub_sock, drain_sock_raw
import msgq
import os
import capnp
@@ -17,8 +18,12 @@ from cereal.services import SERVICE_LIST
NO_TRAVERSAL_LIMIT = 2**64-1
def log_from_bytes(dat: bytes) -> capnp.lib.capnp._DynamicStructReader:
with log.Event.from_bytes(dat, traversal_limit_in_words=NO_TRAVERSAL_LIMIT) as msg:
def reset_context():
msgq.context = Context()
def log_from_bytes(dat: bytes, struct: capnp.lib.capnp._StructModule = log.Event) -> capnp.lib.capnp._DynamicStructReader:
with struct.from_bytes(dat, traversal_limit_in_words=NO_TRAVERSAL_LIMIT) as msg:
return msg
+21 -31
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
import os
import capnp
import multiprocessing
@@ -6,8 +5,8 @@ import numbers
import random
import threading
import time
import unittest
from parameterized import parameterized
import pytest
from cereal import log, car
import cereal.messaging as messaging
@@ -28,12 +27,6 @@ def zmq_sleep(t=1):
if "ZMQ" in os.environ:
time.sleep(t)
def zmq_expected_failure(func):
if "ZMQ" in os.environ:
return unittest.expectedFailure(func)
else:
return func
# TODO: this should take any capnp struct and returrn a msg with random populated data
def random_carstate():
@@ -58,12 +51,12 @@ def delayed_send(delay, sock, dat):
threading.Timer(delay, send_func).start()
class TestMessaging(unittest.TestCase):
class TestMessaging:
def setUp(self):
# TODO: ZMQ tests are too slow; all sleeps will need to be
# replaced with logic to block on the necessary condition
if "ZMQ" in os.environ:
raise unittest.SkipTest
pytest.skip()
# ZMQ pub socket takes too long to die
# sleep to prevent multiple publishers error between tests
@@ -75,9 +68,9 @@ class TestMessaging(unittest.TestCase):
msg = messaging.new_message(evt)
except capnp.lib.capnp.KjException:
msg = messaging.new_message(evt, random.randrange(200))
self.assertLess(time.monotonic() - msg.logMonoTime, 0.1)
self.assertFalse(msg.valid)
self.assertEqual(evt, msg.which())
assert (time.monotonic() - msg.logMonoTime) < 0.1
assert not msg.valid
assert evt == msg.which()
@parameterized.expand(events)
def test_pub_sock(self, evt):
@@ -99,8 +92,8 @@ class TestMessaging(unittest.TestCase):
# no wait and no msgs in queue
msgs = func(sub_sock)
self.assertIsInstance(msgs, list)
self.assertEqual(len(msgs), 0)
assert isinstance(msgs, list)
assert len(msgs) == 0
# no wait but msgs are queued up
num_msgs = random.randrange(3, 10)
@@ -108,9 +101,9 @@ class TestMessaging(unittest.TestCase):
pub_sock.send(messaging.new_message(sock).to_bytes())
time.sleep(0.1)
msgs = func(sub_sock)
self.assertIsInstance(msgs, list)
self.assertTrue(all(isinstance(msg, expected_type) for msg in msgs))
self.assertEqual(len(msgs), num_msgs)
assert isinstance(msgs, list)
assert all(isinstance(msg, expected_type) for msg in msgs)
assert len(msgs) == num_msgs
def test_recv_sock(self):
sock = "carState"
@@ -120,14 +113,14 @@ class TestMessaging(unittest.TestCase):
# no wait and no msg in queue, socket should timeout
recvd = messaging.recv_sock(sub_sock)
self.assertTrue(recvd is None)
assert recvd is None
# no wait and one msg in queue
msg = random_carstate()
pub_sock.send(msg.to_bytes())
time.sleep(0.01)
recvd = messaging.recv_sock(sub_sock)
self.assertIsInstance(recvd, capnp._DynamicStructReader)
assert isinstance(recvd, capnp._DynamicStructReader)
# https://github.com/python/mypy/issues/13038
assert_carstate(msg.carState, recvd.carState)
@@ -139,16 +132,16 @@ class TestMessaging(unittest.TestCase):
# no msg in queue, socket should timeout
recvd = messaging.recv_one(sub_sock)
self.assertTrue(recvd is None)
assert recvd is None
# one msg in queue
msg = random_carstate()
pub_sock.send(msg.to_bytes())
recvd = messaging.recv_one(sub_sock)
self.assertIsInstance(recvd, capnp._DynamicStructReader)
assert isinstance(recvd, capnp._DynamicStructReader)
assert_carstate(msg.carState, recvd.carState)
@zmq_expected_failure
@pytest.mark.xfail(condition="ZMQ" in os.environ, reason='ZMQ detected')
def test_recv_one_or_none(self):
sock = "carState"
pub_sock = messaging.pub_sock(sock)
@@ -157,13 +150,13 @@ class TestMessaging(unittest.TestCase):
# no msg in queue, socket shouldn't block
recvd = messaging.recv_one_or_none(sub_sock)
self.assertTrue(recvd is None)
assert recvd is None
# one msg in queue
msg = random_carstate()
pub_sock.send(msg.to_bytes())
recvd = messaging.recv_one_or_none(sub_sock)
self.assertIsInstance(recvd, capnp._DynamicStructReader)
assert isinstance(recvd, capnp._DynamicStructReader)
assert_carstate(msg.carState, recvd.carState)
def test_recv_one_retry(self):
@@ -179,7 +172,7 @@ class TestMessaging(unittest.TestCase):
p = multiprocessing.Process(target=messaging.recv_one_retry, args=(sub_sock,))
p.start()
time.sleep(sock_timeout*15)
self.assertTrue(p.is_alive())
assert p.is_alive()
p.terminate()
# wait 15 socket timeouts before sending
@@ -187,9 +180,6 @@ class TestMessaging(unittest.TestCase):
delayed_send(sock_timeout*15, pub_sock, msg.to_bytes())
start_time = time.monotonic()
recvd = messaging.recv_one_retry(sub_sock)
self.assertGreaterEqual(time.monotonic() - start_time, sock_timeout*15)
self.assertIsInstance(recvd, capnp._DynamicStructReader)
assert (time.monotonic() - start_time) >= sock_timeout*15
assert isinstance(recvd, capnp._DynamicStructReader)
assert_carstate(msg.carState, recvd.carState)
if __name__ == "__main__":
unittest.main()
+19 -25
View File
@@ -1,8 +1,6 @@
#!/usr/bin/env python3
import random
import time
from typing import Sized, cast
import unittest
import cereal.messaging as messaging
from cereal.messaging.tests.test_messaging import events, random_sock, random_socks, \
@@ -10,9 +8,9 @@ from cereal.messaging.tests.test_messaging import events, random_sock, random_so
zmq_sleep
class TestSubMaster(unittest.TestCase):
class TestSubMaster:
def setUp(self):
def setup_method(self):
# ZMQ pub socket takes too long to die
# sleep to prevent multiple publishers error between tests
zmq_sleep(3)
@@ -21,21 +19,21 @@ class TestSubMaster(unittest.TestCase):
sm = messaging.SubMaster(events)
for p in [sm.updated, sm.recv_time, sm.recv_frame, sm.alive,
sm.sock, sm.data, sm.logMonoTime, sm.valid]:
self.assertEqual(len(cast(Sized, p)), len(events))
assert len(cast(Sized, p)) == len(events)
def test_init_state(self):
socks = random_socks()
sm = messaging.SubMaster(socks)
self.assertEqual(sm.frame, -1)
self.assertFalse(any(sm.updated.values()))
self.assertFalse(any(sm.alive.values()))
self.assertTrue(all(t == 0. for t in sm.recv_time.values()))
self.assertTrue(all(f == 0 for f in sm.recv_frame.values()))
self.assertTrue(all(t == 0 for t in sm.logMonoTime.values()))
assert sm.frame == -1
assert not any(sm.updated.values())
assert not any(sm.alive.values())
assert all(t == 0. for t in sm.recv_time.values())
assert all(f == 0 for f in sm.recv_frame.values())
assert all(t == 0 for t in sm.logMonoTime.values())
for p in [sm.updated, sm.recv_time, sm.recv_frame, sm.alive,
sm.sock, sm.data, sm.logMonoTime, sm.valid]:
self.assertEqual(len(cast(Sized, p)), len(socks))
assert len(cast(Sized, p)) == len(socks)
def test_getitem(self):
sock = "carState"
@@ -59,8 +57,8 @@ class TestSubMaster(unittest.TestCase):
msg = messaging.new_message(sock)
pub_sock.send(msg.to_bytes())
sm.update(1000)
self.assertEqual(sm.frame, i)
self.assertTrue(all(sm.updated.values()))
assert sm.frame == i
assert all(sm.updated.values())
def test_update_timeout(self):
sock = random_sock()
@@ -70,9 +68,9 @@ class TestSubMaster(unittest.TestCase):
start_time = time.monotonic()
sm.update(timeout)
t = time.monotonic() - start_time
self.assertGreaterEqual(t, timeout/1000.)
self.assertLess(t, 5)
self.assertFalse(any(sm.updated.values()))
assert t >= timeout/1000.
assert t < 5
assert not any(sm.updated.values())
def test_avg_frequency_checks(self):
for poll in (True, False):
@@ -118,12 +116,12 @@ class TestSubMaster(unittest.TestCase):
pub_sock.send(msg.to_bytes())
time.sleep(0.01)
sm.update(1000)
self.assertEqual(sm[sock].vEgo, n)
assert sm[sock].vEgo == n
class TestPubMaster(unittest.TestCase):
class TestPubMaster:
def setUp(self):
def setup_method(self):
# ZMQ pub socket takes too long to die
# sleep to prevent multiple publishers error between tests
zmq_sleep(3)
@@ -156,8 +154,4 @@ class TestPubMaster(unittest.TestCase):
if capnp:
msg.clear_write_flag()
msg = msg.to_bytes()
self.assertEqual(msg, recvd, i)
if __name__ == "__main__":
unittest.main()
assert msg == recvd, i
+4 -9
View File
@@ -1,26 +1,21 @@
#!/usr/bin/env python3
import os
import tempfile
from typing import Dict
import unittest
from parameterized import parameterized
import cereal.services as services
from cereal.services import SERVICE_LIST
class TestServices(unittest.TestCase):
class TestServices:
@parameterized.expand(SERVICE_LIST.keys())
def test_services(self, s):
service = SERVICE_LIST[s]
self.assertTrue(service.frequency <= 104)
self.assertTrue(service.decimation != 0)
assert service.frequency <= 104
assert service.decimation != 0
def test_generated_header(self):
with tempfile.NamedTemporaryFile(suffix=".h") as f:
ret = os.system(f"python3 {services.__file__} > {f.name} && clang++ {f.name}")
self.assertEqual(ret, 0, "generated services header is not valid C")
if __name__ == "__main__":
unittest.main()
assert ret == 0, "generated services header is not valid C"
+6 -5
View File
@@ -16,13 +16,13 @@ _services: dict[str, tuple] = {
"gyroscope2": (True, 100., 100),
"accelerometer": (True, 104., 104),
"accelerometer2": (True, 100., 100),
"magnetometer": (True, 25., 25),
"magnetometer": (True, 25.),
"lightSensor": (True, 100., 100),
"temperatureSensor": (True, 2., 200),
"temperatureSensor2": (True, 2., 200),
"gpsNMEA": (True, 9.),
"deviceState": (True, 2., 1),
"can": (True, 100., 1223), # decimation gives ~5 msgs in a full segment
"can": (True, 100., 2053), # decimation gives ~3 msgs in a full segment
"controlsState": (True, 100., 10),
"pandaStates": (True, 10., 1),
"peripheralState": (True, 2., 1),
@@ -38,7 +38,7 @@ _services: dict[str, tuple] = {
"carState": (True, 100., 10),
"carControl": (True, 100., 10),
"carOutput": (True, 100., 10),
"longitudinalPlan": (True, 20., 5),
"longitudinalPlan": (True, 20., 10),
"procLog": (True, 0.5, 15),
"gpsLocationExternal": (True, 10., 10),
"gpsLocation": (True, 1., 1),
@@ -47,9 +47,10 @@ _services: dict[str, tuple] = {
"gnssMeasurements": (True, 10., 10),
"clocks": (True, 0.1, 1),
"ubloxRaw": (True, 20.),
"liveLocationKalman": (True, 20., 5),
"livePose": (True, 20., 4),
"liveLocationKalman": (True, 20.),
"liveParameters": (True, 20., 5),
"cameraOdometry": (True, 20., 5),
"cameraOdometry": (True, 20., 10),
"lateralPlanDEPRECATED": (True, 20., 5),
"thumbnail": (True, 0.2, 1),
"onroadEvents": (True, 1., 1),
+4 -3
View File
@@ -24,8 +24,8 @@ int fsync_dir(const std::string &path) {
int result = -1;
int fd = HANDLE_EINTR(open(path.c_str(), O_RDONLY, 0755));
if (fd >= 0) {
result = fsync(fd);
close(fd);
result = HANDLE_EINTR(fsync(fd));
HANDLE_EINTR(close(fd));
}
return result;
}
@@ -320,7 +320,6 @@ std::unordered_map<std::string, uint32_t> keys = {
{"TorqueLateralJerk", PERSISTENT | BACKUP},
{"TorqueMaxLatAccel", PERSISTENT | BACKUP},
{"TorquedOverride", PERSISTENT | BACKUP},
{"ToyotaAutoHold", PERSISTENT | BACKUP},
{"ToyotaAutoLockBySpeed", PERSISTENT | BACKUP},
{"ToyotaAutoUnlockByShifter", PERSISTENT | BACKUP},
{"ToyotaEnhancedBsm", PERSISTENT | BACKUP},
@@ -338,6 +337,8 @@ std::unordered_map<std::string, uint32_t> keys = {
{"SunnylinkCache_Users", PERSISTENT},
{"SunnylinkCache_Roles", PERSISTENT},
{"EnableGitlabRunner", PERSISTENT | BACKUP},
{"EnableSunnylinkUploader", PERSISTENT | BACKUP},
// PFEIFER - MAPD {{
{"MapdVersion", PERSISTENT},
+2 -2
View File
@@ -47,9 +47,9 @@ class DeviceCameraConfig:
yield cam, getattr(self, cam)
_ar_ox_fisheye = CameraConfig(1928, 1208, 567.0) # focal length probably wrong? magnification is not consistent across frame
_os_fisheye = CameraConfig(2688, 1520, 567.0 / 2 * 3)
_os_fisheye = CameraConfig(2688 // 2, 1520 // 2, 567.0 / 4 * 3)
_ar_ox_config = DeviceCameraConfig(CameraConfig(1928, 1208, 2648.0), _ar_ox_fisheye, _ar_ox_fisheye)
_os_config = DeviceCameraConfig(CameraConfig(2688, 1520, 2648.0 * 2 / 3), _os_fisheye, _os_fisheye)
_os_config = DeviceCameraConfig(CameraConfig(2688 // 2, 1520 // 2, 1522.0 * 3 / 4), _os_fisheye, _os_fisheye)
_neo_config = DeviceCameraConfig(CameraConfig(1164, 874, 910.0), CameraConfig(816, 612, 650.0), _NoneCameraConfig())
DEVICE_CAMERAS = {
+2 -3
View File
@@ -4,7 +4,7 @@
A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified.
# 288 Supported Cars
# 287 Supported Cars
|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|<a href="##"><img width=2000></a>Hardware Needed<br>&nbsp;|Video|
|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
@@ -25,8 +25,7 @@ A supported vehicle is one that just works when you install a comma device. All
|Chrysler|Pacifica 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica 2017-18">Buy Here</a></sub></details>||
|Chrysler|Pacifica 2019-20|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica 2019-20">Buy Here</a></sub></details>||
|Chrysler|Pacifica 2021-23|All|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica 2021-23">Buy Here</a></sub></details>||
|Chrysler|Pacifica Hybrid 2017|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica Hybrid 2017">Buy Here</a></sub></details>||
|Chrysler|Pacifica Hybrid 2018|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica Hybrid 2018">Buy Here</a></sub></details>||
|Chrysler|Pacifica Hybrid 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica Hybrid 2017-18">Buy Here</a></sub></details>||
|Chrysler|Pacifica Hybrid 2019-24|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica Hybrid 2019-24">Buy Here</a></sub></details>||
|comma|body|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|None||
|CUPRA|Ateca 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=CUPRA&model=Ateca 2018-23">Buy Here</a></sub></details>||
+25 -2
View File
@@ -1,3 +1,26 @@
# openpilot-docs
# openpilot docs
These docs are autogenerated from [this folder](https://github.com/commaai/openpilot/tree/master/docs) in the main openpilot repository.
This is the source for [docs.comma.ai](https://docs.comma.ai).
The site is updated on pushes to master by this [workflow](../.github/workflows/docs.yaml).
## Development
NOTE: Those commands must be run in the root directory of openpilot, **not /docs**
**1. Install the docs dependencies**
``` bash
pip install .[docs]
```
**2. Build the new site**
``` bash
mkdocs build
```
**3. Run the new site locally**
``` bash
mkdocs serve
```
References:
* https://www.mkdocs.org/getting-started/
* https://github.com/ntno/mkdocs-terminal
+1 -1
View File
@@ -29,7 +29,7 @@ pytest
cd system/loggerd && pytest .
# run the linter
pre-commit run --all
op lint
```
## Testing
+22
View File
@@ -0,0 +1,22 @@
# What is a car port?
A car port enables openpilot support on a particular car. Each car model openpilot supports needs to be individually ported. All car ports live in `openpilot/selfdrive/car/`.
The complexity of a car port varies depending on many factors including:
* existing openpilot support for similar cars
* architecture and APIs available in the car
# Structure of a car port
* `interface.py`: Interface for the car, defines the CarInterface class
* `carstate.py`: Reads CAN from car and builds openpilot CarState message
* `carcontroller.py`: Builds CAN messages to send to car
* `values.py`: Limits for actuation, general constants for cars, and supported car documentation
* `radar_interface.py`: Interface for parsing radar points from the car
# Overiew
[Jason Young](https://github.com/jyoung8607) gave a talk at COMMA_CON with an overview of the car porting process. The talk is available on YouTube:
https://youtu.be/KcfzEHB6ms4?si=5szh1PX6TksOCKmM
+8
View File
@@ -0,0 +1,8 @@
# openpilot glossary
* **route**:
* **segment**: routes are split into one minute chunks called segments.
* **panda**: this is . See the repo.
* **onroad**:
* **offroad**:
* **comma 3X**:
@@ -1,10 +1,8 @@
# loggerd
# Logging
openpilot records routes in one minute chunks called segments. A route starts on the rising edge of ignition and ends on the falling edge.
Check out our [python library](https://github.com/commaai/openpilot/blob/master/tools/lib/logreader.py) for reading openpilot logs. Also checkout our [tools](https://github.com/commaai/openpilot/tree/master/tools) to replay and view your data. These are the same tools we use to debug and develop openpilot.
## log types
Check out our [Python library](https://github.com/commaai/openpilot/blob/master/tools/lib/logreader.py) for reading openpilot logs. Also checkout our [tools](https://github.com/commaai/openpilot/tree/master/tools) to replay and view your data. These are the same tools we use to debug and develop openpilot.
For each segment, openpilot records the following log types:
@@ -15,9 +13,10 @@ rlogs contain all the messages passed amongst openpilot's processes. See [cereal
## {f,e,d}camera.hevc
Each camera stream is H.265 encoded and written to its respective file.
* fcamera.hevc is the road camera
* ecamera.hevc is the wide road camera
* dcamera.hevc is the driver camera
* `fcamera.hevc` is the road camera
* `ecamera.hevc` is the wide road camera
* `dcamera.hevc` is the driver camera
## qlog.bz2 & qcamera.ts
+1
View File
@@ -0,0 +1 @@
../SAFETY.md
+1
View File
@@ -0,0 +1 @@
# Architecture
+30
View File
@@ -0,0 +1,30 @@
# Roadmap
This is the roadmap for the next major openpilot releases. Also check out
* [Milestones](https://github.com/commaai/openpilot/milestones) for minor releases
* [Projects](https://github.com/commaai/openpilot/projects?query=is%3Aopen) for shorter-term projects not tied to releases
* [Bounties](https://comma.ai/bounties) for paid individual issues
## openpilot 0.10
openpilot 0.10 will be the first release with a driving policy trained in
a [learned simulator](https://youtu.be/EqQNZXqzFSI).
* Driving model trained in a learned simlator
* Always-on driver monitoring (behind a toggle)
* GPS removed from the driving stack
* 100KB qlogs
* `master-ci` pushed after 1000 hours of hardware-in-the-loop testing
* Car interface code moved into [opendbc](https://github.com/commaai/opendbc)
* openpilot on PC for Linux x86, Linux arm64, and Mac (Apple Silicon)
## openpilot 1.0
openpilot 1.0 will feature a fully end-to-end driving policy.
* End-to-end longitudinal control in Chill mode
* Automatic Emergency Braking (AEB)
* Driver monitoring with sleep detection
* Rolling updates/releases pushed out by CI
* [panda safety 1.0](https://github.com/orgs/commaai/projects/27)
@@ -1,6 +1,6 @@
# What is openpilot?
[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, openpilot performs the functions of Adaptive Cruise Control (ACC), Automated Lane Centering (ALC), Forward Collision Warning (FCW), and Lane Departure Warning (LDW) for a growing variety of [supported car makes, models, and model years](docs/CARS.md). In addition, while openpilot is engaged, a camera-based Driver Monitoring (DM) feature alerts distracted and asleep drivers. See more about [the vehicle integration](docs/INTEGRATION.md) and [limitations](docs/LIMITATIONS.md).
[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, openpilot performs the functions of Adaptive Cruise Control (ACC), Automated Lane Centering (ALC), Forward Collision Warning (FCW), and Lane Departure Warning (LDW) for a growing variety of [supported car makes, models, and model years](https://github.com/commaai/openpilot/blob/master/docs/CARS.md). In addition, while openpilot is engaged, a camera-based Driver Monitoring (DM) feature alerts distracted and asleep drivers. See more about [the vehicle integration](https://github.com/commaai/openpilot/blob/master/docs/INTEGRATION.md) and [limitations](https://github.com/commaai/openpilot/blob/master/docs/LIMITATIONS.md).
## How do I use it?
@@ -1,39 +1,42 @@
# SSH
# connect to a comma 3/3X
## Quick Start
A comma 3/3X is a normal [Linux](https://github.com/commaai/agnos-builder) computer that exposes [SSH](https://wiki.archlinux.org/title/Secure_Shell) and a [serial console](https://wiki.archlinux.org/title/Working_with_the_serial_console).
## Serial Console
On both the comma three and 3X, the serial console is accessible from the main OBD-C port.
Connect the comma 3/3X to your computer with a normal USB C cable, or use a [comma serial](https://comma.ai/shop/comma-serial) for steady 12V power.
On the comma three, the serial console is exposed through a UART-to-USB chip, and `tools/serial/connect.sh` can be used to connect.
On the comma 3X, the serial console is accessible through the [panda](https://github.com/commaai/panda) using the `panda/tests/som_debug.sh` script.
## SSH
In order to SSH into your device, you'll need a GitHub account with SSH keys. See this [GitHub article](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh) for getting your account setup with SSH keys.
* Enable SSH in your device's settings
* Enter your GitHub username in the device's settings
* Connect to your device
* Username: `comma`
* Port: `22` or `8022`
* Username: `comma`
* Port: `22`
Here's an example command for connecting to your device using its tethered connection:<br />
`ssh comma@192.168.43.1`
For doing development work on device, it's recommended to use [SSH agent forwarding](https://docs.github.com/en/developers/overview/using-ssh-agent-forwarding).
## Notes
### Notes
The public keys are only fetched from your GitHub account once. In order to update your device's authorized keys, you'll need to re-enter your GitHub username.
The `id_rsa` key in this directory only works while your device is in the setup state with no software installed. After installation, that default key will be removed.
See the [community wiki](https://github.com/commaai/openpilot/wiki/SSH) for more detailed instructions and information.
#### ssh.comma.ai proxy
# Connecting to ssh.comma.ai
SSH into your comma device from anywhere with `ssh.comma.ai`. Requires a [comma prime subscription](https://comma.ai/connect).
With a [comma prime subscription](https://comma.ai/connect), you can SSH into your comma device from anywhere.
## Setup
With software version 0.6.1 or newer, enter your GitHub username on your device under Developer Settings. Your GitHub authorized public keys will become your authorized SSH keys for `ssh.comma.ai`. You can add any additional keys in `/system/comma/home/.ssh/authorized_keys.persist`.
## Recommended .ssh/config
With the below SSH configuration, you can type `ssh comma-{dongleid}` to connect to your device through `ssh.comma.ai`.<br />
For example: `ssh comma-ffffffffffffffff`
With the below SSH configuration, you can type `ssh comma-{dongleid}` to connect to your device through `ssh.comma.ai`.
```
Host comma-*
@@ -41,20 +44,21 @@ Host comma-*
User comma
IdentityFile ~/.ssh/my_github_key
ProxyCommand ssh %h@ssh.comma.ai -W %h:%p
Host ssh.comma.ai
Hostname ssh.comma.ai
Port 22
IdentityFile ~/.ssh/my_github_key
```
## One-off connection
### One-off connection
```
ssh -i ~/.ssh/my_github_key -o ProxyCommand="ssh -i ~/.ssh/my_github_key -W %h:%p -p %p %h@ssh.comma.ai" comma@ffffffffffffffff
```
(Replace `ffffffffffffffff` with your dongle_id)
## ssh.comma.ai host key fingerprint
### ssh.comma.ai host key fingerprint
```
Host key fingerprint is SHA256:X22GOmfjGb9J04IA2+egtdaJ7vW9Fbtmpz9/x8/W1X4
+14
View File
@@ -0,0 +1,14 @@
# Replay
Replaying is a critical tool for openpilot development and debugging.
## Replaying a route
*Hardware required: none*
Just run `tools/replay/replay --demo`.
## Replaying CAN data
*Hardware required: jungle and comma 3/3X*
1. Connect your PC to a jungle.
2.
+98
View File
@@ -0,0 +1,98 @@
# Turn the speed blue
*A getting started guide for openpilot development*
In 30 minutes, we'll get an openpilot development environment setup on your computer and make some changes to openpilot's UI.
And if you have a comma 3/3X, we'll deploy the change to your device for testing.
## 1. Setup your development environment
Run this to clone openpilot and install all the dependencies:
```bash
curl -fsSL openpilot.comma.ai | bash
```
Navigate to openpilot folder & activate a Python virtual environment
```bash
cd openpilot
source .venv/bin/activate
```
Then, compile openpilot:
```bash
scons -j8
```
## 2. Run replay
We'll run the `replay` tool with the demo route to get data streaming for testing our UI changes.
```bash
# in terminal 1
tools/replay/replay --demo
# in terminal 2
selfdrive/ui/ui
```
The openpilot UI should launch and show a replay of the demo route.
If you have your own comma device, you can replace `--demo` with one of your own routes from comma connect.
## 3. Make the speed blue
Search for “mph” with git grep in the `ui` folder.
```bash
$ git grep "mph" selfdrive/ui/
paint.cc: ui_draw_text(s, s->fb_w/2, 290, s->scene.is_metric ? "km/h" : "mph", 36 * 2.5, COLOR_WHITE_ALPHA(200), "sans-regular");
```
The line right above contains the actual speed. Unfortunately, COLOR_BLUE isnt defined, but a git grep of COLOR_WHITE shows its nvgRGBA(255, 255, 255, 255). Personally, I like a lighter blue, so I went with #8080FF.
```bash
$ git diff
diff --git a/selfdrive/ui/paint.cc b/selfdrive/ui/paint.cc
index 821d95115..cc996eaa1 100644
--- a/selfdrive/ui/paint.cc
+++ b/selfdrive/ui/paint.cc
@@ -175,8 +175,8 @@ static void ui_draw_vision_speed(UIState *s) {
const float speed = std::max(0.0, (*s->sm)["carState"].getCarState().getVEgo() * (s->scene.is_metric ? 3.6 : 2.2369363));
const std::string speed_str = std::to_string((int)std::nearbyint(speed));
nvgTextAlign(s->vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
- ui_draw_text(s, s->fb_w/2, 210, speed_str.c_str(), 96 * 2.5, COLOR_WHITE, "sans-bold");
- ui_draw_text(s, s->fb_w/2, 290, s->scene.is_metric ? "km/h" : "mph", 36 * 2.5, COLOR_WHITE_ALPHA(200), "sans-regular");
+ ui_draw_text(s, s->fb_w/2, 210, speed_str.c_str(), 96 * 2.5, nvgRGBA(128, 128, 255, 255), "sans-bold");
+ ui_draw_text(s, s->fb_w/2, 290, s->scene.is_metric ? "km/h" : "mph", 36 * 2.5, nvgRGBA(128, 128, 255, 200), "sans-regular");
}
static void ui_draw_vision_event(UIState *s) {
```
## 4. Rebuild UI, and admire your work
```
scons -j8 && selfdrive/ui/ui
```
![](https://blog.comma.ai/img/blue_speed_ui.png)
## 5. Push your fork to GitHub
Click fork on GitHub. Then, push with:
```bash
git remote rm origin
git remote add origin git@github.com:<your-github-username>/openpilot.git
git add .
git commit -m "Make the speed blue."
git push --set-upstream origin master
```
## 6. Run your fork on device in your car!
Uninstall openpilot from your device through the settings. Then, enter the URL for your very own installer:
```
installer.comma.ai/<your-github-username>/master
```
## 7. Admire your work IRL
![](https://blog.comma.ai/img/c3_blue_ui.jpg)
+1
View File
@@ -0,0 +1 @@
getting-started/what-is-openpilot.md
-12
View File
@@ -1,12 +0,0 @@
This is the source for a new https://docs.comma.ai. It's not hosted anywhere yet, but it's easy to run locally.
https://www.mkdocs.org/getting-started/
```
pip install mkdocs mkdocs-terminal
mkdocs serve
```
inspiration:
* https://rerun.io/docs/
* https://docs.expo.dev/
@@ -1,9 +0,0 @@
# What is a car port?
All car ports live in `openpilot/selfdrive/car/`.
* interface.py: Interface for the car, defines the CarInterface class
* carstate.py: Reads CAN from car and builds openpilot CarState message
* carcontroller.py: Builds CAN messages to send to car
* values.py: Limits for actuation, general constants for cars, and supported car documentation
* radar_interface.py: Interface for parsing radar points from the car
@@ -1,4 +0,0 @@
This section is for how-to's on common workflows.
They'll be like this blog post we wrote:
https://blog.comma.ai/turning-the-speed-blue/
-18
View File
@@ -1,18 +0,0 @@
site_name: openpilot docs
docs_dir: docs
repo_url: https://github.com/commaai/openpilot/
theme:
name: terminal
features:
- navigation.side.toc.hide
nav:
- Getting Started:
- What is openpilot?: getting-started/what-is-openpilot.md
- How-to:
- Turn the speed blue: how-to/turning-the-speed-blue.md
- Car Porting:
- What is a car port?: car-porting/what-is-a-car-port.md
- Porting a car brand: car-porting/brand-port.md
- Porting a car model: car-porting/model-port.md
+38
View File
@@ -0,0 +1,38 @@
site_name: openpilot docs
repo_url: https://github.com/commaai/openpilot/
site_url: https://docs.comma.ai
exclude_docs: README.md
strict: true
docs_dir: docs
site_dir: docs_site/
theme:
name: readthedocs
navigation_depth: 3
nav:
- Getting Started:
- What is openpilot?: getting-started/what-is-openpilot.md
- How-to:
- Turn the speed blue: how-to/turn-the-speed-blue.md
- Connect to a comma 3/3X: how-to/connect-to-comma.md
#- Replay a drive: how-to/replay-a-drive.md
- Concepts:
- Logs: concepts/logs.md
- Safety: concepts/safety.md
- Car Porting:
- What is a car port?: car-porting/what-is-a-car-port.md
- Porting a car brand: car-porting/brand-port.md
- Porting a car model: car-porting/model-port.md
- Contributing:
- Roadmap: contributing/roadmap.md
#- Architecture: contributing/architecture.md
- Contributing Guide →: https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md
- Links:
- Blog →: https://blog.comma.ai
- Bounties →: https://comma.ai/bounties
- GitHub →: https://github.com/commaai
- Discord →: https://discord.comma.ai
- X →: https://x.com/comma_ai
Submodule opendbc deleted from adc1fffe60
Symlink
+1
View File
@@ -0,0 +1 @@
opendbc_repo/opendbc
Submodule
+1
Submodule opendbc_repo added at 529474a50e
+1 -1
Submodule panda updated: ff1ef85735...6a6cd44519
+28 -22
View File
@@ -26,7 +26,7 @@ dependencies = [
"pycapnp",
"Cython",
"setuptools",
"numpy < 2.0.0", # control does not support numpy 2
"numpy",
# body / webrtcd
"aiohttp",
@@ -52,27 +52,30 @@ dependencies = [
"websocket_client",
# acados deps
"casadi",
"casadi @ https://github.com/commaai/casadi/releases/download/nightly-release-3.6.6/casadi-3.6.6-cp312-none-manylinux2014_aarch64.whl ; (python_version == '3.12' and platform_machine == 'aarch64')", # TODO: Go back to pypi casadi when they fix aarch64 for python312
"casadi; platform_machine != 'aarch64' or python_version != '3.12'",
"future-fstrings",
# these should be removed
"psutil",
"pycryptodome", # used in updated/casync, panda, body, and a test
#logreader
"zstd",
# logreader
"zstandard",
]
[project.optional-dependencies]
docs = [
"Jinja2",
"natsort",
"mkdocs",
]
testing = [
"coverage",
"hypothesis ==6.47.*",
"import-linter",
"mypy",
"pre-commit",
"pytest",
"pytest-cov",
"pytest-cpp",
@@ -83,30 +86,25 @@ testing = [
"pytest-asyncio",
"pytest-mock",
"pytest-repeat",
"ruff"
"ruff",
"codespell",
]
dev = [
"av",
"azure-identity",
"azure-storage-blob",
"breathe",
"control",
"dictdiffer",
"flaky",
"inputs",
"lru-dict",
"matplotlib",
"metadrive-simulator; platform_machine != 'aarch64'",
"mpld3",
"myst-parser",
"natsort",
"opencv-python-headless",
"metadrive-simulator@git+https://github.com/commaai/metadrive@opencv_headless ; platform_machine != 'aarch64'",
"parameterized >=0.8, <0.9",
#pprofile = "*"
#"pprofile",
"pyautogui",
"pygame",
"pyopencl; platform_machine != 'aarch64'", # broken on arm64
"pytools < 2024.1.11; platform_machine != 'aarch64'", # pyopencl use a broken version
"pywinctl",
"pyprof2calltree",
"rerun-sdk",
@@ -116,12 +114,8 @@ dev = [
# this is only pinned since 5.15.11 is broken
"pyqt5 ==5.15.2; platform_machine == 'x86_64'", # no aarch64 wheels for macOS/linux
]
[tool.uv.sources]
metadrive-simulator = { git = "https://github.com/commaai/metadrive.git", branch = "opencv_headless" }
[project.urls]
Homepage = "https://comma.ai"
@@ -132,9 +126,12 @@ build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = [ "." ]
[tool.hatch.metadata]
allow-direct-references = true
[tool.pytest.ini_options]
minversion = "6.0"
addopts = "--ignore=openpilot/ --ignore=cereal/ --ignore=opendbc/ --ignore=panda/ --ignore=rednose_repo/ --ignore=tinygrad_repo/ --ignore=teleoprtc_repo/ --ignore=msgq/ -Werror --strict-config --strict-markers --durations=10 -n auto --dist=loadgroup"
addopts = "--ignore=openpilot/ --ignore=opendbc/ --ignore=panda/ --ignore=rednose_repo/ --ignore=tinygrad_repo/ --ignore=teleoprtc_repo/ --ignore=msgq/ -Werror --strict-config --strict-markers --durations=10 -n auto --dist=loadgroup"
cpp_files = "test_*"
cpp_harness = "selfdrive/test/cpp_harness.py"
python_files = "test_*.py"
@@ -167,6 +164,13 @@ testpaths = [
"cereal/messaging/tests",
]
[tool.codespell]
count = true
quiet-level = 3
# if you've got a short variable name that's getting flagged, add it here
ignore-words-list = "bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn"
builtin = "clear,rare,informal,usage,code,names,en-GB_to_en-US"
[tool.mypy]
python_version = "3.11"
plugins = [
@@ -223,7 +227,7 @@ lint.ignore = [
"UP038", # (x, y) -> x|y for isinstance
]
line-length = 160
target-version="py311"
target-version ="py311"
exclude = [
"body",
"cereal",
@@ -235,7 +239,8 @@ exclude = [
"teleoprtc_repo",
"third_party",
]
lint.flake8-implicit-str-concat.allow-multiline=false
lint.flake8-implicit-str-concat.allow-multiline = false
[tool.ruff.lint.flake8-tidy-imports.banned-api]
"selfdrive".msg = "Use openpilot.selfdrive"
"common".msg = "Use openpilot.common"
@@ -247,5 +252,6 @@ lint.flake8-implicit-str-concat.allow-multiline=false
[tool.coverage.run]
concurrency = ["multiprocessing", "thread"]
[tool.ruff.format]
quote-style = "preserve"
@@ -2,7 +2,7 @@
"embeds": [
{
"title": "🎉 sunnypilot `${NEW_BRANCH}` New Update 🎉",
"description": "[sunnypilot](${PUBLIC_REPO_URL}): Build #${CI_PIPELINE_IID} of branch [${NEW_BRANCH}](${PUBLIC_REPO_URL}/tree/${NEW_BRANCH}) has been published.\n\nDrive safe! 🚗💨",
"description": "[sunnypilot](${PUBLIC_REPO_URL}): Build #${EXTRA_VERSION_IDENTIFIER} of branch [${NEW_BRANCH}](${PUBLIC_REPO_URL}/tree/${NEW_BRANCH}) has been published.\n\nDrive safe! 🚗💨",
"color": 4321431
}
]
Regular → Executable
+1 -1
View File
@@ -4,4 +4,4 @@ mv .lfsconfig-comma .lfsconfig
git lfs fetch --all; git lfs pull
mv .lfsconfig .lfsconfig-comma
mv .lfsconfig.bak .lfsconfig
git lfs fetch --all; git lfs push origin main
git lfs fetch --all; git lfs push --all origin
+51 -54
View File
@@ -10,14 +10,12 @@ ROOT = HERE + "/.."
# - minimizing release download size
# - keeping the diff readable
blacklist = [
"body/STL/",
"panda/drivers/",
"panda/examples/",
"panda/tests/safety/",
"opendbc/.*.dbc$",
"opendbc/generator/",
"opendbc_repo/dbc/.*.dbc$",
"opendbc_repo/dbc/generator/",
"cereal/.*test.*",
"^common/tests/",
@@ -28,7 +26,6 @@ blacklist = [
"selfdrive/car/tests/test_models.*",
"^tools/",
"^scripts/",
"^tinygrad_repo/",
"matlab.*.md",
@@ -118,55 +115,55 @@ whitelist = [
"tinygrad_repo/tinygrad/.*.py",
# TODO: do this automatically
"opendbc/comma_body.dbc",
"opendbc/chrysler_ram_hd_generated.dbc",
"opendbc/chrysler_ram_dt_generated.dbc",
"opendbc/chrysler_pacifica_2017_hybrid_generated.dbc",
"opendbc/chrysler_pacifica_2017_hybrid_private_fusion.dbc",
"opendbc/gm_global_a_powertrain_generated.dbc",
"opendbc/gm_global_a_object.dbc",
"opendbc/gm_global_a_chassis.dbc",
"opendbc/FORD_CADS.dbc",
"opendbc/ford_fusion_2018_adas.dbc",
"opendbc/ford_lincoln_base_pt.dbc",
"opendbc/honda_accord_2018_can_generated.dbc",
"opendbc/acura_ilx_2016_can_generated.dbc",
"opendbc/acura_rdx_2018_can_generated.dbc",
"opendbc/acura_rdx_2020_can_generated.dbc",
"opendbc/honda_civic_touring_2016_can_generated.dbc",
"opendbc/honda_civic_hatchback_ex_2017_can_generated.dbc",
"opendbc/honda_crv_touring_2016_can_generated.dbc",
"opendbc/honda_crv_ex_2017_can_generated.dbc",
"opendbc/honda_crv_ex_2017_body_generated.dbc",
"opendbc/honda_crv_executive_2016_can_generated.dbc",
"opendbc/honda_fit_ex_2018_can_generated.dbc",
"opendbc/honda_odyssey_exl_2018_generated.dbc",
"opendbc/honda_odyssey_extreme_edition_2018_china_can_generated.dbc",
"opendbc/honda_insight_ex_2019_can_generated.dbc",
"opendbc/acura_ilx_2016_nidec.dbc",
"opendbc/honda_civic_ex_2022_can_generated.dbc",
"opendbc/hyundai_canfd.dbc",
"opendbc/hyundai_kia_generic.dbc",
"opendbc/hyundai_kia_mando_front_radar_generated.dbc",
"opendbc/mazda_2017.dbc",
"opendbc/nissan_x_trail_2017_generated.dbc",
"opendbc/nissan_leaf_2018_generated.dbc",
"opendbc/subaru_global_2017_generated.dbc",
"opendbc/subaru_global_2020_hybrid_generated.dbc",
"opendbc/subaru_outback_2015_generated.dbc",
"opendbc/subaru_outback_2019_generated.dbc",
"opendbc/subaru_forester_2017_generated.dbc",
"opendbc/toyota_tnga_k_pt_generated.dbc",
"opendbc/toyota_new_mc_pt_generated.dbc",
"opendbc/toyota_nodsu_pt_generated.dbc",
"opendbc/toyota_adas.dbc",
"opendbc/toyota_tss2_adas.dbc",
"opendbc/vw_golf_mk4.dbc",
"opendbc/vw_mqb_2010.dbc",
"opendbc/tesla_can.dbc",
"opendbc/tesla_radar_bosch_generated.dbc",
"opendbc/tesla_radar_continental_generated.dbc",
"opendbc/tesla_powertrain.dbc",
"opendbc_repo/dbc/comma_body.dbc",
"opendbc_repo/dbc/chrysler_ram_hd_generated.dbc",
"opendbc_repo/dbc/chrysler_ram_dt_generated.dbc",
"opendbc_repo/dbc/chrysler_pacifica_2017_hybrid_generated.dbc",
"opendbc_repo/dbc/chrysler_pacifica_2017_hybrid_private_fusion.dbc",
"opendbc_repo/dbc/gm_global_a_powertrain_generated.dbc",
"opendbc_repo/dbc/gm_global_a_object.dbc",
"opendbc_repo/dbc/gm_global_a_chassis.dbc",
"opendbc_repo/dbc/FORD_CADS.dbc",
"opendbc_repo/dbc/ford_fusion_2018_adas.dbc",
"opendbc_repo/dbc/ford_lincoln_base_pt.dbc",
"opendbc_repo/dbc/honda_accord_2018_can_generated.dbc",
"opendbc_repo/dbc/acura_ilx_2016_can_generated.dbc",
"opendbc_repo/dbc/acura_rdx_2018_can_generated.dbc",
"opendbc_repo/dbc/acura_rdx_2020_can_generated.dbc",
"opendbc_repo/dbc/honda_civic_touring_2016_can_generated.dbc",
"opendbc_repo/dbc/honda_civic_hatchback_ex_2017_can_generated.dbc",
"opendbc_repo/dbc/honda_crv_touring_2016_can_generated.dbc",
"opendbc_repo/dbc/honda_crv_ex_2017_can_generated.dbc",
"opendbc_repo/dbc/honda_crv_ex_2017_body_generated.dbc",
"opendbc_repo/dbc/honda_crv_executive_2016_can_generated.dbc",
"opendbc_repo/dbc/honda_fit_ex_2018_can_generated.dbc",
"opendbc_repo/dbc/honda_odyssey_exl_2018_generated.dbc",
"opendbc_repo/dbc/honda_odyssey_extreme_edition_2018_china_can_generated.dbc",
"opendbc_repo/dbc/honda_insight_ex_2019_can_generated.dbc",
"opendbc_repo/dbc/acura_ilx_2016_nidec.dbc",
"opendbc_repo/dbc/honda_civic_ex_2022_can_generated.dbc",
"opendbc_repo/dbc/hyundai_canfd.dbc",
"opendbc_repo/dbc/hyundai_kia_generic.dbc",
"opendbc_repo/dbc/hyundai_kia_mando_front_radar_generated.dbc",
"opendbc_repo/dbc/mazda_2017.dbc",
"opendbc_repo/dbc/nissan_x_trail_2017_generated.dbc",
"opendbc_repo/dbc/nissan_leaf_2018_generated.dbc",
"opendbc_repo/dbc/subaru_global_2017_generated.dbc",
"opendbc_repo/dbc/subaru_global_2020_hybrid_generated.dbc",
"opendbc_repo/dbc/subaru_outback_2015_generated.dbc",
"opendbc_repo/dbc/subaru_outback_2019_generated.dbc",
"opendbc_repo/dbc/subaru_forester_2017_generated.dbc",
"opendbc_repo/dbc/toyota_tnga_k_pt_generated.dbc",
"opendbc_repo/dbc/toyota_new_mc_pt_generated.dbc",
"opendbc_repo/dbc/toyota_nodsu_pt_generated.dbc",
"opendbc_repo/dbc/toyota_adas.dbc",
"opendbc_repo/dbc/toyota_tss2_adas.dbc",
"opendbc_repo/dbc/vw_golf_mk4.dbc",
"opendbc_repo/dbc/vw_mqb_2010.dbc",
"opendbc_repo/dbc/tesla_can.dbc",
"opendbc_repo/dbc/tesla_radar_bosch_generated.dbc",
"opendbc_repo/dbc/tesla_radar_continental_generated.dbc",
"opendbc_repo/dbc/tesla_powertrain.dbc",
]
# Sunnypilot whitelist
+390
View File
@@ -0,0 +1,390 @@
#!/bin/bash -e
SRC=/tmp/openpilot/
SRC_CLONE=/tmp/openpilot-clone/
OUT=/tmp/openpilot-tiny/
REWRITE_IGNORE_BRANCHES=(
dashcam3
devel
master-ci
nightly
release2
release3
release3-staging
)
VALIDATE_IGNORE_FILES=(
".github/ISSUE_TEMPLATE/bug_report.md"
".github/pull_request_template.md"
)
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd $DIR
LOGS_DIR=$DIR/git-rewrite-$(date +"%Y-%m-%dT%H:%M:%S%z")
mkdir -p $LOGS_DIR
GIT_REWRITE_LOG=$LOGS_DIR/git-rewrite-log.txt
BRANCH_DIFF_LOG=$LOGS_DIR/branch-diff-log.txt
COMMIT_DIFF_LOG=$LOGS_DIR/commit-diff-log.txt
START_TIME=$(date +%s)
exec > >(while IFS= read -r line; do
CURRENT_TIME=$(date +%s)
ELAPSED_TIME=$((CURRENT_TIME - START_TIME))
echo "[${ELAPSED_TIME}s] $line"
done | tee -a "$GIT_REWRITE_LOG") 2>&1
# INSTALL git-filter-repo
if [ ! -f /tmp/git-filter-repo ]; then
echo "Installing git-filter-repo..."
curl -sSo /tmp/git-filter-repo https://raw.githubusercontent.com/newren/git-filter-repo/main/git-filter-repo
chmod +x /tmp/git-filter-repo
fi
# MIRROR openpilot
if [ ! -d $SRC ]; then
echo "Mirroring openpilot..."
git clone --mirror https://github.com/commaai/openpilot.git $SRC # 4.18 GiB (488034 objects)
cd $SRC
echo "Starting size $(du -sh .)"
git remote update
# the git-filter-repo analysis is bliss - can be found in the repo root/filter-repo/analysis
echo "Analyzing with git-filter-repo..."
/tmp/git-filter-repo --force --analyze
echo "Pushing to openpilot-archive..."
# push to archive repo - in smaller parts because the 2 GB push limit - https://docs.github.com/en/get-started/using-git/troubleshooting-the-2-gb-push-limit
ARCHIVE_REPO=git@github.com:commaai/openpilot-archive.git
git push --prune $ARCHIVE_REPO +refs/heads/master:refs/heads/master # push master first so it's the default branch (when openpilot-archive is an empty repo)
git push --prune $ARCHIVE_REPO +refs/heads/*:refs/heads/* # 956.39 MiB (110725 objects)
git push --prune $ARCHIVE_REPO +refs/tags/*:refs/tags/* # 1.75 GiB (21694 objects)
# git push --mirror $ARCHIVE_REPO || true # fails to push refs/pull/* (deny updating a hidden ref) for pull requests
# we fail and continue - more reading: https://stackoverflow.com/a/34266401/639708 and https://blog.plataformatec.com.br/2013/05/how-to-properly-mirror-a-git-repository/
fi
# REWRITE master and tags
if [ ! -d $SRC_CLONE ]; then
echo "Cloning $SRC..."
GIT_LFS_SKIP_SMUDGE=1 git clone $SRC $SRC_CLONE
cd $SRC_CLONE
echo "Checking out old history..."
git checkout tags/v0.7.1 > /dev/null 2>&1
# checkout as main, since we need master ref later
git checkout -b main
echo "Creating setup commits..."
# rm these so we don't get conflicts later
git rm -r cereal opendbc panda selfdrive/ui/ui > /dev/null
git commit -m "removed conflicting files" > /dev/null
# skip-smudge to get rid of some lfs errors that it can't find the reference of some lfs files
# we don't care about fetching/pushing lfs right now
git lfs install --skip-smudge --local
# squash initial setup commits
git cherry-pick -n -X theirs 6c33a5c..59b3d06 > /dev/null
git commit -m "switching to master" > /dev/null
# squash the two commits
git reset --soft HEAD~2
git commit -m "switching to master" -m "$(git log --reverse --format=%B 6c33a5c..59b3d06)" -m "removed conflicting files" > /dev/null
# get commits we want to cherry-pick
# will start with the next commit after #59b3d06 tools is local now
COMMITS=$(git rev-list --reverse 59b3d06..master)
# we need this for logging
TOTAL_COMMITS=$(echo $COMMITS | wc -w | xargs)
CURRENT_COMMIT_NUMBER=0
# empty this file
> commit-map.txt
echo "Rewriting master commits..."
for COMMIT in $COMMITS; do
CURRENT_COMMIT_NUMBER=$((CURRENT_COMMIT_NUMBER + 1))
# echo -ne "[$CURRENT_COMMIT_NUMBER/$TOTAL_COMMITS] Cherry-picking commit: $COMMIT"\\r
echo "[$CURRENT_COMMIT_NUMBER/$TOTAL_COMMITS] Cherry-picking commit: $COMMIT"
# set environment variables to preserve author/committer and dates
export GIT_AUTHOR_NAME=$(git show -s --format='%an' $COMMIT)
export GIT_AUTHOR_EMAIL=$(git show -s --format='%ae' $COMMIT)
export GIT_COMMITTER_NAME=$(git show -s --format='%cn' $COMMIT)
export GIT_COMMITTER_EMAIL=$(git show -s --format='%ce' $COMMIT)
export GIT_AUTHOR_DATE=$(git show -s --format='%ad' $COMMIT)
export GIT_COMMITTER_DATE=$(git show -s --format='%cd' $COMMIT)
# cherry-pick the commit
if ! GIT_OUTPUT=$(git cherry-pick -m 1 -X theirs $COMMIT 2>&1); then
# check if the failure is because of an empty commit
if [[ "$GIT_OUTPUT" == *"The previous cherry-pick is now empty"* ]]; then
echo "Empty commit detected. Skipping commit $COMMIT"
git cherry-pick --skip
# log it was empty to the mapping file
echo "$COMMIT EMPTY" >> commit-map.txt
else
# handle other errors or conflicts
echo "Cherry-pick failed. Handling error..."
echo "$GIT_OUTPUT"
exit 1
fi
else
# capture the new commit hash
NEW_COMMIT=$(git rev-parse HEAD)
# save the old and new commit hashes to the mapping file
echo "$COMMIT $NEW_COMMIT" >> commit-map.txt
# append the old commit ID to the commit message
git commit --amend -m "$(git log -1 --pretty=%B)" -m "Former-commit-id: $COMMIT" > /dev/null
fi
# prune every 3000 commits to avoid gc errors
if [ $((CURRENT_COMMIT_NUMBER % 3000)) -eq 0 ]; then
echo "Pruning repo..."
git gc
fi
done
echo "Rewriting tags..."
# remove all old tags
git tag -l | xargs git tag -d
# read each line from the tag-commit-map.txt
while IFS=' ' read -r TAG OLD_COMMIT; do
# search for the new commit in commit-map.txt corresponding to the old commit
NEW_COMMIT=$(grep "^$OLD_COMMIT " "commit-map.txt" | awk '{print $2}')
# check if this is a rebased commit
if [ -z "$NEW_COMMIT" ]; then
# if not, then just use old commit hash
NEW_COMMIT=$OLD_COMMIT
fi
echo "Rewriting tag $TAG from commit $NEW_COMMIT"
git tag -f "$TAG" "$NEW_COMMIT"
done < "$DIR/tag-commit-map.txt"
# uninstall lfs since we don't want to touch (push to) lfs right now
# git push will also push lfs, if we don't uninstall (--local so just for this repo)
git lfs uninstall --local
# force push new master
git push --force origin main:master
# force push new tags
git push --force --tags
fi
# REWRITE branches based on master
if [ ! -f "$SRC_CLONE/rewrite-branches-done" ]; then
cd $SRC_CLONE
> rewrite-branches-done
# empty file
> $BRANCH_DIFF_LOG
echo "Rewriting branches based on master..."
# will store raw diffs here, if exist
mkdir -p differences
# get a list of all branches except master and REWRITE_IGNORE_BRANCHES
BRANCHES=$(git branch -r | grep -v ' -> ' | sed 's/.*origin\///' | grep -v '^master$' | grep -v -f <(echo "${REWRITE_IGNORE_BRANCHES[*]}" | tr ' ' '\n'))
for BRANCH in $BRANCHES; do
# check if the branch is based on master history
MERGE_BASE=$(git merge-base master origin/$BRANCH) || true
if [ -n "$MERGE_BASE" ]; then
echo "Rewriting branch: $BRANCH"
# create a new branch based on the new master
NEW_MERGE_BASE=$(grep "^$MERGE_BASE " "commit-map.txt" | awk '{print $2}')
if [ -z "$NEW_MERGE_BASE" ]; then
echo "Error: could not find new merge base for branch $BRANCH" >> $BRANCH_DIFF_LOG
continue
fi
git checkout -b ${BRANCH}_new $NEW_MERGE_BASE
# get the range of commits unique to this branch
COMMITS=$(git rev-list --reverse $MERGE_BASE..origin/${BRANCH})
HAS_ERROR=0
# simple delimiter
echo "BRANCH ${BRANCH}" >> commit-map.txt
for COMMIT in $COMMITS; do
# set environment variables to preserve author/committer and dates
export GIT_AUTHOR_NAME=$(git show -s --format='%an' $COMMIT)
export GIT_AUTHOR_EMAIL=$(git show -s --format='%ae' $COMMIT)
export GIT_COMMITTER_NAME=$(git show -s --format='%cn' $COMMIT)
export GIT_COMMITTER_EMAIL=$(git show -s --format='%ce' $COMMIT)
export GIT_AUTHOR_DATE=$(git show -s --format='%ad' $COMMIT)
export GIT_COMMITTER_DATE=$(git show -s --format='%cd' $COMMIT)
# cherry-pick the commit
if ! GIT_OUTPUT=$(git cherry-pick -m 1 -X theirs $COMMIT 2>&1); then
# check if the failure is because of an empty commit
if [[ "$GIT_OUTPUT" == *"The previous cherry-pick is now empty"* ]]; then
echo "Empty commit detected. Skipping commit $COMMIT"
git cherry-pick --skip
# log it was empty to the mapping file
echo "$COMMIT EMPTY" >> commit-map.txt
else
# handle other errors or conflicts
echo "Cherry-pick of ${BRANCH} branch failed. Removing branch upstream..." >> $BRANCH_DIFF_LOG
echo "$GIT_OUTPUT" > "$LOGS_DIR/branch-${BRANCH}"
git cherry-pick --abort
git push --delete origin ${BRANCH}
HAS_ERROR=1
break
fi
else
# capture the new commit hash
NEW_COMMIT=$(git rev-parse HEAD)
# save the old and new commit hashes to the mapping file
echo "$COMMIT $NEW_COMMIT" >> commit-map.txt
# append the old commit ID to the commit message
git commit --amend -m "$(git log -1 --pretty=%B)" -m "Former-commit-id: $COMMIT" > /dev/null
fi
done
# force push the new branch
if [ $HAS_ERROR -eq 0 ]; then
# git lfs goes haywire here, so we need to install and uninstall
# git lfs install --skip-smudge --local
git lfs uninstall --local > /dev/null
git push -f origin ${BRANCH}_new:${BRANCH}
fi
# clean up local branch
git checkout master > /dev/null
git branch -D ${BRANCH}_new > /dev/null
else
echo "Deleting branch $BRANCH as it's not based on master history" >> $BRANCH_DIFF_LOG
git push --delete origin ${BRANCH}
fi
done
fi
# VALIDATE cherry-pick
if [ ! -f "$SRC_CLONE/validation-done" ]; then
cd $SRC_CLONE
> validation-done
TOTAL_COMMITS=$(grep -cve '^\s*$' commit-map.txt)
CURRENT_COMMIT_NUMBER=0
COUNT_SAME=0
COUNT_DIFF=0
# empty file
> $COMMIT_DIFF_LOG
echo "Validating commits..."
# will store raw diffs here, if exist
mkdir -p differences
# read each line from commit-map.txt
while IFS=' ' read -r OLD_COMMIT NEW_COMMIT; do
if [ "$NEW_COMMIT" == "EMPTY" ]; then
continue
fi
if [ "$OLD_COMMIT" == "BRANCH" ]; then
echo "Branch ${NEW_COMMIT} below:" >> $COMMIT_DIFF_LOG
continue
fi
CURRENT_COMMIT_NUMBER=$((CURRENT_COMMIT_NUMBER + 1))
# retrieve short hashes and dates for the old and new commits
OLD_COMMIT_SHORT=$(git rev-parse --short $OLD_COMMIT)
NEW_COMMIT_SHORT=$(git rev-parse --short $NEW_COMMIT)
OLD_DATE=$(git show -s --format='%cd' $OLD_COMMIT)
NEW_DATE=$(git show -s --format='%cd' $NEW_COMMIT)
# echo -ne "[$CURRENT_COMMIT_NUMBER/$TOTAL_COMMITS] Comparing old commit $OLD_COMMIT_SHORT ($OLD_DATE) with new commit $NEW_COMMIT_SHORT ($NEW_DATE)"\\r
echo "[$CURRENT_COMMIT_NUMBER/$TOTAL_COMMITS] Comparing old commit $OLD_COMMIT_SHORT ($OLD_DATE) with new commit $NEW_COMMIT_SHORT ($NEW_DATE)"
# generate lists of files and their hashes for the old and new commits, excluding ignored files
OLD_FILES=$(git ls-tree -r $OLD_COMMIT | grep -vE "$(IFS='|'; echo "${VALIDATE_IGNORE_FILES[*]}")")
NEW_FILES=$(git ls-tree -r $NEW_COMMIT | grep -vE "$(IFS='|'; echo "${VALIDATE_IGNORE_FILES[*]}")")
# Compare the diffs
if diff <(echo "$OLD_FILES") <(echo "$NEW_FILES") > /dev/null; then
# echo "Old commit $OLD_COMMIT_SHORT and new commit $NEW_COMMIT_SHORT are equivalent."
COUNT_SAME=$((COUNT_SAME + 1))
else
echo "[$CURRENT_COMMIT_NUMBER/$TOTAL_COMMITS] Difference found between old commit $OLD_COMMIT_SHORT and new commit $NEW_COMMIT_SHORT" >> $COMMIT_DIFF_LOG
COUNT_DIFF=$((COUNT_DIFF + 1))
set +e
diff -u <(echo "$OLD_FILES") <(echo "$NEW_FILES") > "$LOGS_DIR/commit-$CURRENT_COMMIT_NUMBER-$OLD_COMMIT_SHORT-$NEW_COMMIT_SHORT"
set -e
fi
done < "commit-map.txt"
echo "Summary:" >> $COMMIT_DIFF_LOG
echo "Equivalent commits: $COUNT_SAME" >> $COMMIT_DIFF_LOG
echo "Different commits: $COUNT_DIFF" >> $COMMIT_DIFF_LOG
fi
if [ ! -d $OUT ]; then
cp -r $SRC $OUT
cd $OUT
# remove all non-master branches
# git branch | grep -v "^ master$" | grep -v "\*" | xargs git branch -D
# echo "cleaning up refs"
# delete pull request refs since we can't alter them anyway (https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally#error-failed-to-push-some-refs)
# git for-each-ref --format='%(refname)' | grep '^refs/pull/' | xargs -I {} git update-ref -d {}
echo "importing new lfs files"
# import "almost" everything to lfs
BRANCHES=$(git for-each-ref --format='%(refname)' refs/heads/ | sed 's%refs/heads/%%g' | grep -v -f <(echo "${REWRITE_IGNORE_BRANCHES[*]}" | tr ' ' '\n') | tr '\n' ' ')
git lfs migrate import --include="*.dlc,*.onnx,*.svg,*.png,*.gif,*.ttf,*.wav,selfdrive/car/tests/test_models_segs.txt,system/hardware/tici/updater,selfdrive/ui/qt/spinner_larch64,selfdrive/ui/qt/text_larch64,third_party/**/*.a,third_party/**/*.so,third_party/**/*.so.*,third_party/**/*.dylib,third_party/acados/*/t_renderer,third_party/qt5/larch64/bin/lrelease,third_party/qt5/larch64/bin/lupdate,third_party/catch2/include/catch2/catch.hpp,*.apk,*.apkpatch,*.jar,*.pdf,*.jpg,*.mp3,*.thneed,*.tar.gz,*.npy,*.csv,*.a,*.so*,*.dylib,*.o,*.b64,selfdrive/hardware/tici/updater,selfdrive/boardd/tests/test_boardd,selfdrive/ui/qt/spinner_aarch64,installer/updater/updater,selfdrive/debug/profiling/simpleperf/**/*,selfdrive/hardware/eon/updater,selfdrive/ui/qt/text_aarch64,selfdrive/debug/profiling/pyflame/**/*,installer/installers/installer_openpilot,installer/installers/installer_dashcam,selfdrive/ui/text/text,selfdrive/ui/android/text/text,selfdrive/ui/spinner/spinner,selfdrive/visiond/visiond,selfdrive/loggerd/loggerd,selfdrive/sensord/sensord,selfdrive/sensord/gpsd,selfdrive/ui/android/spinner/spinner,selfdrive/ui/qt/spinner,selfdrive/ui/qt/text,_stringdefs.py,dfu-util-aarch64-linux,dfu-util-aarch64,dfu-util-x86_64-linux,dfu-util-x86_64,stb_image.h,clpeak3,clwaste,apk/**/*,external/**/*,phonelibs/**/*,third_party/boringssl/**/*,flask/**/*,panda/**/*,board/**/*,messaging/**/*,opendbc/**/*,tools/cabana/chartswidget.cc,third_party/nanovg/**/*,selfdrive/controls/lib/lateral_mpc/lib_mpc_export/**/*,selfdrive/ui/paint.cc,werkzeug/**/*,pyextra/**/*,third_party/android_hardware_libhardware/**/*,selfdrive/controls/lib/lead_mpc_lib/lib_mpc_export/**/*,selfdrive/locationd/laikad.py,selfdrive/locationd/test/test_laikad.py,tools/gpstest/test_laikad.py,selfdrive/locationd/laikad_helpers.py,tools/nui/**/*,jsonrpc/**/*,selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/**/*,selfdrive/controls/lib/lateral_mpc/mpc_export/**/*,selfdrive/camerad/cameras/camera_qcom.cc,selfdrive/manager.py,selfdrive/modeld/models/driving.cc,third_party/curl/**/*,selfdrive/modeld/thneed/debug/**/*,selfdrive/modeld/thneed/include/**/*,third_party/openmax/**/*,selfdrive/controls/lib/longitudinal_mpc/mpc_export/**/*,selfdrive/controls/lib/longitudinal_mpc_model/lib_mpc_export/**/*,Pipfile,Pipfile.lock,gunicorn/**/*,*.qm,jinja2/**/*,click/**/*,dbcs/**/*,websocket/**/*" $BRANCHES
echo "reflog and gc"
# this is needed after lfs import
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# check the git-filter-repo analysis again - can be found in the repo root/filter-repo/analysis
echo "Analyzing with git-filter-repo..."
/tmp/git-filter-repo --force --analyze
echo "New size is $(du -sh .)"
fi
cd $OUT
# fetch all lfs files from https://github.com/commaai/openpilot.git
# some lfs files are missing on gitlab, but they can be found on github
git config lfs.url https://github.com/commaai/openpilot.git/info/lfs
git config lfs.pushurl ssh://git@github.com/commaai/openpilot.git
git lfs fetch --all || true
# also fetch all lfs files from https://gitlab.com/commaai/openpilot-lfs.git
git config lfs.url https://gitlab.com/commaai/openpilot-lfs.git/info/lfs
git config lfs.pushurl ssh://git@gitlab.com/commaai/openpilot-lfs.git
git lfs fetch --all || true
# final push - will also push lfs
# TODO: switch to git@github.com:commaai/openpilot.git when ready
# git push --mirror git@github.com:commaai/openpilot-tiny.git
# using this instead to ignore refs/pull/* - since this is also what --mirror does - https://blog.plataformatec.com.br/2013/05/how-to-properly-mirror-a-git-repository/
git push --prune git@github.com:commaai/openpilot-tiny.git +refs/heads/*:refs/heads/* +refs/tags/*:refs/tags/*
+82
View File
@@ -0,0 +1,82 @@
v0.1 e94a30bec07e719c5a7b037ca1f4db8312702cce
v0.2 449b482cc3236ccf31829830b4f6a44b2dcc06c2
v0.2.1 17d9becd3c673091b22f09aa02559a9ed9230f50
v0.2.2 a64b9aa9b8cb5863c917b6926516291a63c02fe5
v0.2.3 adaa4ed350acda4067fc0b455ad15b54cdf4c768
v0.2.4 ecc565aa3fdc4c7e719aadc000e1fdc4d80d4fe0
v0.2.5 29c58b45882ac79595356caf98580c1d2a626011
v0.2.6 6c3afeec0fb439070b2912978b8dbb659033b1d9
v0.2.7 c6ba5dc5391d3ca6cda479bf1923b88ce45509a0
v0.2.8 95a349abcc050712c50d4d85a1c8a804eee7f6c2
v0.2.9 693bcb0f83478f2651db6bac9be5ca5ad60d03f3
v0.3.0 c5d8aec28b5230d34ae4b677c2091cc3dec7e3e8
v0.3.1 41e3a0f699f5c39cb61a15c0eb7a4aa816d47c24
v0.3.2 7fe46f1e1df5dec08a940451ba0feefd5c039165
v0.3.3 5cf91d0496688fed4f2a6c7021349b1fc0e057a2
v0.3.4 1b8c44b5067525a5d266b6e99799d8097da76a29
v0.3.5 b111277f464cf66fa34b67819a83ea683e0f64df
v0.4.0.2 da52d065a4c4f52d6017a537f3a80326f5af8bdc
v0.4.1 4474b9b3718653aeb0aee26422caefb90460cc0e
v0.4.2 28c0797d30175043bbfa31307b63aab4197cf996
v0.4.4 9a9ff839a9b70cb2601d7696af743f5652395389
v0.4.5 37285038d3f91fa1b49159c4a35a8383168e644f
v0.4.6 c6df34f55ba8c5a911b60d3f9eb20e3fa45f68c1
v0.4.7 ae5cb7a0dab8b1bed9d52292f9b4e8e66a0f8ec9
v0.5 de33bc46452b1046387ee2b3a03191b2c71135fb
v0.5.1 8f22f52235c48eada586795ac57edb22688e4d08
v0.5.2 0129a8a4ff8da5314e8e4d4d3336e89667ff6d54
v0.5.3 285c52eb693265a0a530543e9ca0aeb593a2a55e
v0.5.4 a422246dc30bce11e970514f13f7c110f4470cc3
v0.5.5 8f3539a27b28851153454eb737da9624cccaed2d
v0.5.6 860a48765d1016ba226fb2c64aea35a45fe40e4a
v0.5.7 9ce3045f139ee29bf0eea5ec59dfe7df9c3d2c51
v0.5.8 2cee2e05ba0f3824fdbb8b957958800fa99071a1
v0.5.9 ad145da3bcded0fe75306df02061d07a633963c3
v0.5.10 ff4c1557d8358f158f4358788ff18ef93d2470ef
v0.5.11 d1866845df423c6855e2b365ff230cf7d89a420b
v0.5.12 f6e8ef27546e9a406724841e75f8df71cc4c2c97
v0.5.13 dd34ccfe288ebda8e2568cf550994ae890379f45
v0.6 60a20537c5f3fcc7f11946d81aebc8f90c08c117
v0.6.1 cf5c4aeacb1703d0ffd35bdb5297d3494fee9a22
v0.6.2 095ef5f9f60fca1b269aabcc3cfd322b17b9e674
v0.6.3 d5f9caa82d80cdcc7f1b7748f2cf3ccbf94f82a3
v0.6.4 58f376002e0c654fbc2de127765fa297cf694a33
v0.6.5 70d17cd69b80e7627dcad8fd5b6438f2309ac307
v0.6.6 d4eb5a6eafdd4803d09e6f3963918216cca5a81f
v0.7 a2ae18d1dbd1e59c38ce22fa25ddffbd1d3084e3
v0.7.1 1e1de64a1e59476b7b3d3558b92149246d5c3292
v0.7.2 59bd58c940673b4c4a6a86f299022614bcf42b22
v0.7.3 d7acd8b68f8131e0e714400cf124a3e228638643
v0.7.4 e93649882c5e914eec4a8b8b593dc0587e497033
v0.7.5 8abc0afe464626a461d2c7e192c912eeebeccc65
v0.7.6 69aacd9d179fe6dd3110253a099c38b34cff7899
v0.7.7 f1caed7299cdba5e45635d8377da6cc1e5fd7072
v0.7.8 2189fe8741b635d8394d55dee28959425cfd5ad0
v0.7.9 86dc54b836a973f132ed26db9f5a60b29f9b25b2
v0.7.10 47a42ff432db8a2494e922ca5e767e58020f0446
v0.7.11 f46ed718ba8d6bb4d42cd7b0f0150c406017c373
v0.8 d56e04c0d960c8d3d4ab88b578dc508a2b4e07dc
v0.8.1 cd6f26664cb8d32a13847d6648567c47c580e248
v0.8.2 7cc0999aebfe63b6bb6dd83c1dff62c3915c4820
v0.8.3 986500fe2f10870018f1fba1e5465476b8915977
v0.8.4 f0d0b82b8d6f5f450952113e234d0a5a49e80c48
v0.8.5 f5d9ddc6c2a2802a61e5ce590c6b6688bf736a69
v0.8.6 75904ed7452c6cbfb2a70cd379a899d8a75b97c2
v0.8.7 4f9e568019492126e236da85b5ca0a059f292900
v0.8.8 a949a49d5efaaf2d881143d23e9fb5ff9e28e88c
v0.8.9 a034926264cd1025c69d6ceb3fe444965f960b75
v0.8.10 59accdd814398b884167c0f41dbf46dcccf0c29c
v0.8.11 d630ec9092f039cb5e51c5dd6d92fc47b91407e4
v0.8.12 57871c99031cf597ffa0d819057ac1401e129f32
v0.8.13 e43e6e876513450d235124fcb711f1724ed9814c
v0.8.14 71901c94dbbaa2f9f156a80c14cc7ea65219fc7c
v0.8.15 5a7c2f90361e72e9c35e88abd2e11acdc4aba354
v0.8.16 f41dc62a12cc0f3cb8c5453c0caa0ba21e1bd01e
v0.9.0 58b84fb401a804967aa0dd5ee66fafa90194fd30
v0.9.1 89f68bf0cbf53a81b0553d3816fdbe522f941fa1
v0.9.2 c7d3b28b93faa6c955fb24bc64031512ee985ee9
v0.9.3 8704c1ff952b5c85a44f50143bbd1a4f7b4887e2
v0.9.4 fa310d9e2542cf497d92f007baec8fd751ffa99c
v0.9.5 3b1e9017c560499786d8a0e46aaaeea65037acac
v0.9.6 0b4d08fab8e35a264bc7383e878538f8083c33e5
v0.9.7 f8cb04e4a8b032b72a909f68b808a50936184bee
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
set -e
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
cd $DIR/../
# TODO: bring back rest of pre-commit checks:
# https://github.com/commaai/openpilot/blob/4b11c9e914707df9def598616995be2a5d355a6a/.pre-commit-config.yaml#L2
ruff check .
-7
View File
@@ -1,7 +0,0 @@
#!/usr/bin/env bash
set -e
pip install --upgrade pyupgrade
git ls-files '*.py' | grep -v 'third_party/' | xargs pyupgrade --py311-plus
+57 -6
View File
@@ -7,10 +7,12 @@ from dataclasses import replace
import capnp
from cereal import car
from panda.python.uds import SERVICE_TYPE
from openpilot.common.numpy_fast import clip, interp
from openpilot.common.utils import Freezable
from openpilot.selfdrive.car.docs_definitions import CarDocs
DT_CTRL = 0.01 # car state and control loop timestep (s)
# kg of standard extra cargo to count for drive, gas, etc...
STD_CARGO_KG = 136.
@@ -43,10 +45,28 @@ def create_button_events(cur_btn: int, prev_btn: int, buttons_dict: dict[int, ca
return events
def create_mads_event(mads_event_lock: bool) -> capnp.lib.capnp._DynamicStructBuilder:
be = car.CarState.ButtonEvent(pressed=mads_event_lock)
be.type = ButtonType.altButton1
return be
class ButtonEvents:
def __init__(self) -> None:
self.is_mads: bool = False
@staticmethod
def create_cancel_event(long_enabled: bool, prev_long_enabled: bool) -> list[capnp.lib.capnp._DynamicStructBuilder]:
events: list[capnp.lib.capnp._DynamicStructBuilder] = []
if not long_enabled and prev_long_enabled:
events.append(car.CarState.ButtonEvent(pressed=True,
type=ButtonType.cancel))
return events
def create_mads_event(self, mads_enabled: bool, prev_mads_enabled: bool) -> list[capnp.lib.capnp._DynamicStructBuilder]:
events: list[capnp.lib.capnp._DynamicStructBuilder] = []
mads_changed = prev_mads_enabled != mads_enabled
if (mads_changed and not self.is_mads) or (not mads_changed and self.is_mads):
events.append(car.CarState.ButtonEvent(pressed=mads_changed, type=ButtonType.altButton1))
self.is_mads = not self.is_mads
return events
def gen_empty_fingerprint():
@@ -198,7 +218,7 @@ def create_gas_interceptor_command(packer, gas_amount, idx):
values["GAS_COMMAND"] = gas_amount * 255.
values["GAS_COMMAND2"] = gas_amount * 255.
dat = packer.make_can_msg("GAS_COMMAND", 0, values)[2]
dat = packer.make_can_msg("GAS_COMMAND", 0, values)[1]
checksum = crc8_pedal(dat[:-1])
values["CHECKSUM_PEDAL"] = checksum
@@ -206,8 +226,39 @@ def create_gas_interceptor_command(packer, gas_amount, idx):
return packer.make_can_msg("GAS_COMMAND", 0, values)
def apply_center_deadzone(error, deadzone):
if (error > - deadzone) and (error < deadzone):
error = 0.
return error
def rate_limit(new_value, last_value, dw_step, up_step):
return clip(new_value, last_value + dw_step, last_value + up_step)
def get_friction(lateral_accel_error: float, lateral_accel_deadzone: float, friction_threshold: float,
torque_params: car.CarParams.LateralTorqueTuning, friction_compensation: bool) -> float:
friction_interp = interp(
apply_center_deadzone(lateral_accel_error, lateral_accel_deadzone),
[-friction_threshold, friction_threshold],
[-torque_params.friction, torque_params.friction]
)
friction = float(friction_interp) if friction_compensation else 0.0
return friction
def make_can_msg(addr, dat, bus):
return [addr, 0, dat, bus]
return [addr, dat, bus]
def make_tester_present_msg(addr, bus, subaddr=None, suppress_response=False):
dat = [0x02, SERVICE_TYPE.TESTER_PRESENT]
if subaddr is not None:
dat.insert(0, subaddr)
dat.append(0x80 if suppress_response else 0x0) # sub-function
dat.extend([0x0] * (8 - len(dat)))
return make_can_msg(addr, bytes(dat), bus)
def get_safety_config(safety_model, safety_param = None):
+2 -2
View File
@@ -1,7 +1,7 @@
import numpy as np
from openpilot.common.realtime import DT_CTRL
from opendbc.can.packer import CANPacker
from openpilot.selfdrive.car import DT_CTRL
from openpilot.selfdrive.car.body import bodycan
from openpilot.selfdrive.car.body.values import SPEED_FROM_RPM
from openpilot.selfdrive.car.interfaces import CarControllerBase
@@ -17,7 +17,7 @@ MAX_TURN_INTEGRATOR = 0.1 # meters
class CarController(CarControllerBase):
def __init__(self, dbc_name, CP, VM):
self.frame = 0
super().__init__(dbc_name, CP, VM)
self.packer = CANPacker(dbc_name)
# PIDs
+1 -2
View File
@@ -1,7 +1,6 @@
import math
from cereal import car
from openpilot.common.realtime import DT_CTRL
from openpilot.selfdrive.car import get_safety_config
from openpilot.selfdrive.car import DT_CTRL, get_safety_config
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
from openpilot.selfdrive.car.body.values import SPEED_FROM_RPM
+26 -8
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env python3
import os
import threading
import time
from types import SimpleNamespace
import cereal.messaging as messaging
@@ -9,11 +11,13 @@ from cereal import car
from panda import ALTERNATIVE_EXPERIENCE
from openpilot.common.params import Params
from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper, DT_CTRL
from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper
from openpilot.selfdrive.pandad import can_list_to_can_capnp
from openpilot.selfdrive.car import DT_CTRL
from openpilot.selfdrive.car.car_helpers import get_car, get_one_can
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
from openpilot.selfdrive.car.param_manager import ParamManager
from openpilot.selfdrive.controls.lib.events import Events
REPLAY = "REPLAY" in os.environ
@@ -56,7 +60,6 @@ class Car:
self.mads_disengage_lateral_on_brake = self.params.get_bool("DisengageLateralOnBrake")
self.mads_dlob = self.enable_mads and self.mads_disengage_lateral_on_brake
self.mads_ndlob = self.enable_mads and not self.mads_disengage_lateral_on_brake
self.sp_toyota_auto_brake_hold = self.params.get_bool("ToyotaAutoHold")
self.CP.alternativeExperience = 0
if not self.disengage_on_accelerator:
self.CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.DISABLE_DISENGAGE_ON_GAS
@@ -64,8 +67,6 @@ class Car:
self.CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.ENABLE_MADS
elif self.mads_ndlob:
self.CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.MADS_DISABLE_DISENGAGE_LATERAL_ON_BRAKE
if self.sp_toyota_auto_brake_hold:
self.CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.ALLOW_AEB
if self.CP.customStockLongAvailable and self.CP.pcmCruise and self.params.get_bool("CustomStockLong"):
self.CP.pcmCruiseSpeed = False
@@ -93,6 +94,10 @@ class Car:
self.events = Events()
self.param_manager: ParamManager = ParamManager()
self.param_manager.update(self.params)
self._params_list: SimpleNamespace = self.param_manager.get_params()
# card is driven by can recv, expected at 100Hz
self.rk = Ratekeeper(100, print_delay_threshold=None)
@@ -101,7 +106,7 @@ class Car:
# Update carState from CAN
can_strs = messaging.drain_sock_raw(self.can_sock, wait_for_one=True)
CS = self.CI.update(self.CC_prev, can_strs)
CS = self.CI.update(self.CC_prev, can_strs, self._params_list)
self.sm.update(0)
@@ -189,10 +194,23 @@ class Car:
self.initialized_prev = initialized
self.CS_prev = CS.as_reader()
def sp_params_thread(self, event: threading.Event) -> None:
while not event.is_set():
self.param_manager.update(self.params)
self._params_list = self.param_manager.get_params()
time.sleep(0.1)
def card_thread(self):
while True:
self.step()
self.rk.monitor_time()
event = threading.Event()
thread = threading.Thread(target=self.sp_params_thread, args=(event, ))
try:
thread.start()
while True:
self.step()
self.rk.monitor_time()
finally:
event.set()
thread.join()
def main():
+18 -23
View File
@@ -1,22 +1,22 @@
from cereal import car
import cereal.messaging as messaging
from common.conversions import Conversions as CV
from opendbc.can.packer import CANPacker
from openpilot.common.params import Params
from openpilot.common.realtime import DT_CTRL
from openpilot.selfdrive.car import apply_meas_steer_torque_limits
from openpilot.selfdrive.car import DT_CTRL, apply_meas_steer_torque_limits
from openpilot.selfdrive.car.chrysler import chryslercan
from openpilot.selfdrive.car.chrysler.values import RAM_CARS, RAM_DT, CarControllerParams, ChryslerFlags, ChryslerFlagsSP
from openpilot.selfdrive.car.interfaces import CarControllerBase, FORWARD_GEARS
from openpilot.selfdrive.controls.lib.drive_helpers import FCA_V_CRUISE_MIN
BUTTONS_STATES = ["accelCruise", "decelCruise", "cancel", "resumeCruise"]
ButtonType = car.CarState.ButtonEvent.Type
class CarController(CarControllerBase):
def __init__(self, dbc_name, CP, VM):
self.CP = CP
super().__init__(dbc_name, CP, VM)
self.apply_steer_last = 0
self.frame = 0
self.hud_count = 0
self.last_lkas_falling_edge = 0
@@ -28,9 +28,6 @@ class CarController(CarControllerBase):
self.sm = messaging.SubMaster(['longitudinalPlanSP'])
self.param_s = Params()
self.is_metric = self.param_s.get_bool("IsMetric")
self.speed_limit_control_enabled = False
self.last_speed_limit_sign_tap = False
self.last_speed_limit_sign_tap_prev = False
self.speed_limit = 0.
self.speed_limit_offset = 0
@@ -70,23 +67,19 @@ class CarController(CarControllerBase):
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
if self.frame % 200 == 0:
self.speed_limit_control_enabled = self.param_s.get_bool("EnableSlc")
self.is_metric = self.param_s.get_bool("IsMetric")
self.last_speed_limit_sign_tap = self.param_s.get_bool("LastSpeedLimitSignTap")
self.v_cruise_min = FCA_V_CRUISE_MIN[self.is_metric] * (CV.KPH_TO_MPH if not self.is_metric else 1)
self.v_cruise_min = FCA_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
can_sends = []
if not self.CP.pcmCruiseSpeed:
if not self.last_speed_limit_sign_tap_prev and self.last_speed_limit_sign_tap:
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
self.sl_force_active_timer = self.frame
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
self.last_speed_limit_sign_tap_prev = self.last_speed_limit_sign_tap
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
sl_force_active = self.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
sl_inactive = not sl_force_active and (not self.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
sl_temp_inactive = not sl_force_active and (self.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
slc_active = not sl_inactive and not sl_temp_inactive
self.slc_active_stock = slc_active
@@ -104,7 +97,7 @@ class CarController(CarControllerBase):
self.last_button_frame = CS.button_counter
if ram_cars:
if CS.buttonStates["cancel"]:
if any(b.type == ButtonType.cancel for b in CS.out.buttonEvents):
can_sends.append(chryslercan.create_cruise_buttons(self.packer, CS.button_counter, das_bus, self.CP, cancel=True))
else:
can_sends.append(chryslercan.create_cruise_buttons(self.packer, CS.button_counter, das_bus, self.CP,
@@ -189,8 +182,10 @@ class CarController(CarControllerBase):
# multikyd methods, sunnyhaibin logic
def get_cruise_buttons_status(self, CS):
if not CS.out.cruiseState.enabled or any(CS.buttonStates[button_state] for button_state in BUTTONS_STATES):
self.timer = 40
if not CS.out.cruiseState.enabled:
for be in CS.out.buttonEvents:
if be.type in (ButtonType.accelCruise, ButtonType.decelCruise, ButtonType.resumeCruise) and be.pressed:
self.timer = 40
elif self.timer:
self.timer -= 1
else:
@@ -274,8 +269,8 @@ class CarController(CarControllerBase):
return min(target_speed_kph, curve_speed)
def get_button_control(self, CS, final_speed, v_cruise_kph_prev):
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not self.is_metric else 1))
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not self.is_metric else CV.MS_TO_KPH))
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1))
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not CS.params_list.is_metric else CV.MS_TO_KPH))
cruise_button = self.get_button_type(self.button_type)
return cruise_button
+12 -9
View File
@@ -3,7 +3,7 @@ from openpilot.common.conversions import Conversions as CV
from opendbc.can.parser import CANParser
from opendbc.can.can_define import CANDefine
from openpilot.selfdrive.car.interfaces import CarStateBase
from openpilot.selfdrive.car.chrysler.values import DBC, STEER_THRESHOLD, RAM_CARS, BUTTON_STATES
from openpilot.selfdrive.car.chrysler.values import DBC, STEER_THRESHOLD, RAM_CARS, BUTTONS
class CarState(CarStateBase):
@@ -29,8 +29,7 @@ class CarState(CarStateBase):
self.lkas_heartbit = None
self.lkas_disabled = False
self.buttonStates = BUTTON_STATES.copy()
self.buttonStatesPrev = BUTTON_STATES.copy()
self.button_states = {button.event_type: False for button in BUTTONS}
def update(self, cp, cp_cam):
@@ -41,7 +40,6 @@ class CarState(CarStateBase):
self.prev_mads_enabled = self.mads_enabled
self.prev_lkas_enabled = self.lkas_enabled
self.buttonStatesPrev = self.buttonStates.copy()
# lock info
ret.doorOpen = any([cp.vl["BCM_1"]["DOOR_OPEN_FL"],
@@ -76,6 +74,16 @@ class CarState(CarStateBase):
unit=1,
)
# Buttons
for button in BUTTONS:
state = (cp.vl[button.can_addr][button.can_msg] in button.values)
if self.button_states[button.event_type] != state:
event = car.CarState.ButtonEvent.new_message()
event.type = button.event_type
event.pressed = state
self.button_events.append(event)
self.button_states[button.event_type] = state
# button presses
ret.leftBlinker, ret.rightBlinker = ret.leftBlinkerOn, ret.rightBlinkerOn = self.update_blinker_from_stalk(200, cp.vl["STEERING_LEVERS"]["TURN_SIGNALS"] == 1,
cp.vl["STEERING_LEVERS"]["TURN_SIGNALS"] == 2)
@@ -116,11 +124,6 @@ class CarState(CarStateBase):
ret.leftBlindspot = cp.vl["BSM_1"]["LEFT_STATUS"] == 1
ret.rightBlindspot = cp.vl["BSM_1"]["RIGHT_STATUS"] == 1
self.buttonStates["accelCruise"] = bool(cp.vl["CRUISE_BUTTONS"]["ACC_Accel"])
self.buttonStates["decelCruise"] = bool(cp.vl["CRUISE_BUTTONS"]["ACC_Decel"])
self.buttonStates["cancel"] = bool(cp.vl["CRUISE_BUTTONS"]["ACC_Cancel"])
self.buttonStates["resumeCruise"] = bool(cp.vl["CRUISE_BUTTONS"]["ACC_Resume"])
self.lkas_car_model = cp_cam.vl["DAS_6"]["CAR_MODEL"]
self.button_counter = cp.vl["CRUISE_BUTTONS"]["COUNTER"]
self.cruise_buttons = cp.vl["CRUISE_BUTTONS"]
+26 -29
View File
@@ -4,35 +4,6 @@ from openpilot.selfdrive.car.chrysler.values import CAR
Ecu = car.CarParams.Ecu
FW_VERSIONS = {
CAR.CHRYSLER_PACIFICA_2017_HYBRID: {
(Ecu.combinationMeter, 0x742, None): [
b'68239262AH',
b'68239262AI',
b'68239262AJ',
b'68239263AH',
b'68239263AJ',
],
(Ecu.srs, 0x744, None): [
b'68238840AH',
],
(Ecu.fwdRadar, 0x753, None): [
b'68226356AI',
],
(Ecu.eps, 0x75a, None): [
b'68288309AC',
b'68288309AD',
],
(Ecu.engine, 0x7e0, None): [
b'68277480AV ',
b'68277480AX ',
b'68277480AZ ',
],
(Ecu.hybrid, 0x7e2, None): [
b'05190175BF',
b'05190175BH',
b'05190226AK',
],
},
CAR.CHRYSLER_PACIFICA_2018: {
(Ecu.combinationMeter, 0x742, None): [
b'68227902AF',
@@ -55,6 +26,7 @@ FW_VERSIONS = {
],
(Ecu.fwdRadar, 0x753, None): [
b'04672758AA',
b'04672758AB',
b'68226356AF',
b'68226356AH',
b'68226356AI',
@@ -76,6 +48,7 @@ FW_VERSIONS = {
b'68352654AE ',
b'68366851AH ',
b'68366853AE ',
b'68366853AG ',
b'68372861AF ',
],
(Ecu.transmission, 0x7e1, None): [
@@ -89,6 +62,7 @@ FW_VERSIONS = {
b'68277374AD',
b'68277374AN',
b'68367471AC',
b'68367471AD',
b'68380571AB',
],
},
@@ -181,26 +155,39 @@ FW_VERSIONS = {
},
CAR.CHRYSLER_PACIFICA_2018_HYBRID: {
(Ecu.combinationMeter, 0x742, None): [
b'68239262AH',
b'68239262AI',
b'68239262AJ',
b'68239263AH',
b'68239263AJ',
b'68358439AE',
b'68358439AG',
],
(Ecu.srs, 0x744, None): [
b'68238840AH',
b'68358990AC',
b'68405939AA',
],
(Ecu.fwdRadar, 0x753, None): [
b'04672758AA',
b'68226356AI',
],
(Ecu.eps, 0x75a, None): [
b'68288309AC',
b'68288309AD',
b'68525339AA',
],
(Ecu.engine, 0x7e0, None): [
b'68277480AV ',
b'68277480AX ',
b'68277480AZ ',
b'68366580AI ',
b'68366580AK ',
b'68366580AM ',
],
(Ecu.hybrid, 0x7e2, None): [
b'05190175BF',
b'05190175BH',
b'05190226AI',
b'05190226AK',
b'05190226AM',
@@ -245,6 +232,7 @@ FW_VERSIONS = {
b'68416680AE ',
b'68416680AF ',
b'68416680AG ',
b'68444228AC ',
b'68444228AD ',
b'68444228AE ',
b'68444228AF ',
@@ -402,6 +390,7 @@ FW_VERSIONS = {
b'68294051AI',
b'68294052AG',
b'68294052AH',
b'68294059AI',
b'68294063AG',
b'68294063AH',
b'68294063AI',
@@ -412,6 +401,7 @@ FW_VERSIONS = {
b'68434858AC',
b'68434859AC',
b'68434860AC',
b'68453471AD',
b'68453483AC',
b'68453483AD',
b'68453487AD',
@@ -436,11 +426,13 @@ FW_VERSIONS = {
b'68527346AE',
b'68527361AD',
b'68527375AD',
b'68527381AD',
b'68527381AE',
b'68527382AE',
b'68527383AD',
b'68527383AE',
b'68527387AE',
b'68527397AD',
b'68527403AC',
b'68527403AD',
b'68546047AF',
@@ -531,6 +523,7 @@ FW_VERSIONS = {
b'05036066AE ',
b'05036193AA ',
b'05149368AA ',
b'05149374AA ',
b'05149591AD ',
b'05149591AE ',
b'05149592AE ',
@@ -561,6 +554,7 @@ FW_VERSIONS = {
b'68455145AC ',
b'68455145AE ',
b'68455146AC ',
b'68460927AA ',
b'68467915AC ',
b'68467916AC ',
b'68467936AC ',
@@ -579,6 +573,7 @@ FW_VERSIONS = {
b'68539650AF',
b'68539651AD',
b'68586101AA ',
b'68586102AA ',
b'68586105AB ',
b'68629919AC ',
b'68629922AC ',
@@ -617,6 +612,8 @@ FW_VERSIONS = {
b'68520867AE',
b'68520867AF',
b'68520870AC',
b'68520871AC',
b'68528325AE',
b'68540431AB',
b'68540433AB',
b'68551676AA',
+16 -30
View File
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
from cereal import car
from panda import Panda
from openpilot.selfdrive.car import create_button_events, get_safety_config, create_mads_event
from openpilot.selfdrive.car.chrysler.values import CAR, RAM_HD, RAM_DT, RAM_CARS, ChryslerFlags, ChryslerFlagsSP, BUTTON_STATES
from openpilot.selfdrive.car import create_button_events, get_safety_config
from openpilot.selfdrive.car.chrysler.values import CAR, RAM_HD, RAM_DT, RAM_CARS, ChryslerFlags, ChryslerFlagsSP
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
ButtonType = car.CarState.ButtonEvent.Type
@@ -13,7 +13,6 @@ GearShifter = car.CarState.GearShifter
class CarInterface(CarInterfaceBase):
def __init__(self, CP, CarController, CarState):
super().__init__(CP, CarController, CarState)
self.buttonStatesPrev = BUTTON_STATES.copy()
@staticmethod
def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs):
@@ -41,8 +40,8 @@ class CarInterface(CarInterfaceBase):
ret.flags |= ChryslerFlags.HIGHER_MIN_STEERING_SPEED.value
# Chrysler
if candidate in (CAR.CHRYSLER_PACIFICA_2017_HYBRID, CAR.CHRYSLER_PACIFICA_2018, CAR.CHRYSLER_PACIFICA_2018_HYBRID, \
CAR.CHRYSLER_PACIFICA_2019_HYBRID, CAR.CHRYSLER_PACIFICA_2020, CAR.DODGE_DURANGO):
if candidate in (CAR.CHRYSLER_PACIFICA_2018, CAR.CHRYSLER_PACIFICA_2018_HYBRID, CAR.CHRYSLER_PACIFICA_2019_HYBRID,
CAR.CHRYSLER_PACIFICA_2020, CAR.DODGE_DURANGO):
ret.lateralTuning.init('pid')
ret.lateralTuning.pid.kpBP, ret.lateralTuning.pid.kiBP = [[9., 20.], [9., 20.]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.15, 0.30], [0.03, 0.05]]
@@ -92,21 +91,17 @@ class CarInterface(CarInterfaceBase):
def _update(self, c):
ret = self.CS.update(self.cp, self.cp_cam)
self.sp_update_params()
buttonEvents = create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise})
for button in self.CS.buttonStates:
if self.CS.buttonStates[button] != self.buttonStatesPrev[button]:
be = car.CarState.ButtonEvent.new_message()
be.type = button
be.pressed = self.CS.buttonStates[button]
buttonEvents.append(be)
self.CS.button_events = [
*self.CS.button_events,
*create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise}),
*create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}),
]
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
buttonEvents, c.vCruise,
self.CS.button_events, c.vCruise,
enable_buttons=(ButtonType.accelCruise, ButtonType.decelCruise, ButtonType.resumeCruise) if not self.CP.pcmCruiseSpeed else
(ButtonType.accelCruise, ButtonType.decelCruise),
resume_button=(ButtonType.resumeCruise,) if not self.CP.pcmCruiseSpeed else
@@ -116,7 +111,7 @@ class CarInterface(CarInterfaceBase):
if self.enable_mads:
if not self.CS.prev_mads_enabled and self.CS.mads_enabled:
self.CS.madsEnabled = True
if self.CS.prev_lkas_enabled != 1 and self.CS.lkas_enabled == 1:
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
self.CS.madsEnabled = not self.CS.madsEnabled
self.CS.lkas_disabled = not self.CS.lkas_disabled
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
@@ -125,7 +120,7 @@ class CarInterface(CarInterfaceBase):
self.CS.madsEnabled = self.get_sp_started_mads(ret, self.CS)
if not self.CP.pcmCruise or (self.CP.pcmCruise and self.CP.minEnableSpeed > 0) or not self.CP.pcmCruiseSpeed:
if any(b.type == ButtonType.cancel for b in buttonEvents):
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
if self.get_sp_pedal_disengage(ret):
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
@@ -143,17 +138,10 @@ class CarInterface(CarInterfaceBase):
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=bool(self.CS.distance_button))
# MADS BUTTON
if self.CS.out.madsEnabled != self.CS.madsEnabled:
if self.mads_event_lock:
buttonEvents.append(create_mads_event(self.mads_event_lock))
self.mads_event_lock = False
else:
if not self.mads_event_lock:
buttonEvents.append(create_mads_event(self.mads_event_lock))
self.mads_event_lock = True
ret.buttonEvents = buttonEvents
ret.buttonEvents = [
*self.CS.button_events,
*self.button_events.create_mads_event(self.CS.madsEnabled, self.CS.out.madsEnabled) # MADS BUTTON
]
# events
events = self.create_common_events(ret, c, extra_gears=[car.CarState.GearShifter.low], pcm_enable=False)
@@ -180,6 +168,4 @@ class CarInterface(CarInterfaceBase):
ret.events = events.to_msg()
self.buttonStatesPrev = self.CS.buttonStates.copy()
return ret
@@ -39,7 +39,6 @@ def _address_to_track(address):
class RadarInterface(RadarInterfaceBase):
def __init__(self, CP):
super().__init__(CP)
self.CP = CP
self.rcp = _create_radar_can_parser(CP.carFingerprint)
self.updated_messages = set()
self.trigger_msg = LAST_MSG
+14 -16
View File
@@ -1,3 +1,4 @@
from collections import namedtuple
from enum import IntFlag
from dataclasses import dataclass, field
@@ -8,6 +9,7 @@ from openpilot.selfdrive.car.docs_definitions import CarHarness, CarDocs, CarPar
from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, p16
Ecu = car.CarParams.Ecu
Button = namedtuple('Button', ['event_type', 'can_addr', 'can_msg', 'values'])
class ChryslerFlags(IntFlag):
@@ -38,34 +40,30 @@ class ChryslerCarSpecs(CarSpecs):
class CAR(Platforms):
# Chrysler
CHRYSLER_PACIFICA_2017_HYBRID = ChryslerPlatformConfig(
[ChryslerCarDocs("Chrysler Pacifica Hybrid 2017")],
ChryslerCarSpecs(mass=2242., wheelbase=3.089, steerRatio=16.2),
)
CHRYSLER_PACIFICA_2018_HYBRID = ChryslerPlatformConfig(
[ChryslerCarDocs("Chrysler Pacifica Hybrid 2018")],
CHRYSLER_PACIFICA_2017_HYBRID.specs,
[ChryslerCarDocs("Chrysler Pacifica Hybrid 2017-18")],
ChryslerCarSpecs(mass=2242., wheelbase=3.089, steerRatio=16.2),
)
CHRYSLER_PACIFICA_2019_HYBRID = ChryslerPlatformConfig(
[ChryslerCarDocs("Chrysler Pacifica Hybrid 2019-24")],
CHRYSLER_PACIFICA_2017_HYBRID.specs,
CHRYSLER_PACIFICA_2018_HYBRID.specs,
)
CHRYSLER_PACIFICA_2018 = ChryslerPlatformConfig(
[ChryslerCarDocs("Chrysler Pacifica 2017-18")],
CHRYSLER_PACIFICA_2017_HYBRID.specs,
CHRYSLER_PACIFICA_2018_HYBRID.specs,
)
CHRYSLER_PACIFICA_2020 = ChryslerPlatformConfig(
[
ChryslerCarDocs("Chrysler Pacifica 2019-20"),
ChryslerCarDocs("Chrysler Pacifica 2021-23", package="All"),
],
CHRYSLER_PACIFICA_2017_HYBRID.specs,
CHRYSLER_PACIFICA_2018_HYBRID.specs,
)
# Dodge
DODGE_DURANGO = ChryslerPlatformConfig(
[ChryslerCarDocs("Dodge Durango 2020-21")],
CHRYSLER_PACIFICA_2017_HYBRID.specs,
CHRYSLER_PACIFICA_2018_HYBRID.specs,
)
# Jeep
@@ -113,12 +111,12 @@ class CarControllerParams:
self.STEER_MAX = 261 # higher than this faults the EPS
BUTTON_STATES = {
"accelCruise": False,
"decelCruise": False,
"cancel": False,
"resumeCruise": False,
}
BUTTONS = [
Button(car.CarState.ButtonEvent.Type.accelCruise, "CRUISE_BUTTONS", "ACC_Accel", [1]),
Button(car.CarState.ButtonEvent.Type.decelCruise, "CRUISE_BUTTONS", "ACC_Decel", [1]),
Button(car.CarState.ButtonEvent.Type.cancel, "CRUISE_BUTTONS", "ACC_Cancel", [1]),
Button(car.CarState.ButtonEvent.Type.resumeCruise, "CRUISE_BUTTONS", "ACC_Resume", [1]),
]
STEER_THRESHOLD = 120
+5 -14
View File
@@ -4,22 +4,13 @@ import time
import cereal.messaging as messaging
from panda.python.uds import SERVICE_TYPE
from openpilot.selfdrive.car import make_can_msg
from openpilot.selfdrive.car import make_tester_present_msg
from openpilot.selfdrive.car.fw_query_definitions import EcuAddrBusType
from openpilot.selfdrive.pandad import can_list_to_can_capnp
from openpilot.common.swaglog import cloudlog
def make_tester_present_msg(addr, bus, subaddr=None):
dat = [0x02, SERVICE_TYPE.TESTER_PRESENT, 0x0]
if subaddr is not None:
dat.insert(0, subaddr)
dat.extend([0x0] * (8 - len(dat)))
return make_can_msg(addr, bytes(dat), bus)
def is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subaddr: int = None) -> bool:
def _is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subaddr: int = None) -> bool:
# ISO-TP messages are always padded to 8 bytes
# tester present response is always a single frame
dat_offset = 1 if subaddr is not None else 0
@@ -33,7 +24,7 @@ def is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subadd
return False
def get_all_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, bus: int, timeout: float = 1, debug: bool = True) -> set[EcuAddrBusType]:
def _get_all_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, bus: int, timeout: float = 1, debug: bool = True) -> set[EcuAddrBusType]:
addr_list = [0x700 + i for i in range(256)] + [0x18da00f1 + (i << 8) for i in range(256)]
queries: set[EcuAddrBusType] = {(addr, None, bus) for addr in addr_list}
responses = queries
@@ -58,7 +49,7 @@ def get_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, que
continue
subaddr = None if (msg.address, None, msg.src) in responses else msg.dat[0]
if (msg.address, subaddr, msg.src) in responses and is_tester_present_response(msg, subaddr):
if (msg.address, subaddr, msg.src) in responses and _is_tester_present_response(msg, subaddr):
if debug:
print(f"CAN-RX: {hex(msg.address)} - 0x{bytes.hex(msg.dat)}")
if (msg.address, subaddr, msg.src) in ecu_responses:
@@ -94,7 +85,7 @@ if __name__ == "__main__":
set_obd_multiplexing(params, not args.no_obd)
print("Getting ECU addresses ...")
ecu_addrs = get_all_ecu_addrs(logcan, sendcan, args.bus, args.timeout, debug=args.debug)
ecu_addrs = _get_all_ecu_addrs(logcan, sendcan, args.bus, args.timeout, debug=args.debug)
print()
print("Found ECUs on rx addresses:")
+2 -1
View File
@@ -130,7 +130,8 @@ MIGRATION = {
# Removal of platform_str, see https://github.com/commaai/openpilot/pull/31868/
"COMMA BODY": BODY.COMMA_BODY,
"CHRYSLER PACIFICA HYBRID 2017": CHRYSLER.CHRYSLER_PACIFICA_2017_HYBRID,
"CHRYSLER PACIFICA HYBRID 2017": CHRYSLER.CHRYSLER_PACIFICA_2018_HYBRID,
"CHRYSLER_PACIFICA_2017_HYBRID": CHRYSLER.CHRYSLER_PACIFICA_2018_HYBRID,
"CHRYSLER PACIFICA HYBRID 2018": CHRYSLER.CHRYSLER_PACIFICA_2018_HYBRID,
"CHRYSLER PACIFICA HYBRID 2019": CHRYSLER.CHRYSLER_PACIFICA_2019_HYBRID,
"CHRYSLER PACIFICA 2018": CHRYSLER.CHRYSLER_PACIFICA_2018,
+3 -3
View File
@@ -5,10 +5,10 @@ from openpilot.selfdrive.car import apply_std_steer_angle_limits
from openpilot.selfdrive.car.ford import fordcan
from openpilot.selfdrive.car.ford.values import CarControllerParams, FordFlags
from openpilot.selfdrive.car.interfaces import CarControllerBase
from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX
LongCtrlState = car.CarControl.Actuators.LongControlState
VisualAlert = car.CarControl.HUDControl.VisualAlert
V_CRUISE_MAX = 145
def apply_ford_curvature_limits(apply_curvature, apply_curvature_last, current_curvature, v_ego_raw):
@@ -25,11 +25,10 @@ def apply_ford_curvature_limits(apply_curvature, apply_curvature_last, current_c
class CarController(CarControllerBase):
def __init__(self, dbc_name, CP, VM):
self.CP = CP
super().__init__(dbc_name, CP, VM)
self.VM = VM
self.packer = CANPacker(dbc_name)
self.CAN = fordcan.CanBus(CP)
self.frame = 0
self.apply_curvature_last = 0
self.main_on_last = False
@@ -92,6 +91,7 @@ class CarController(CarControllerBase):
if not CC.longActive or gas < CarControllerParams.MIN_GAS:
gas = CarControllerParams.INACTIVE_GAS
stopping = CC.actuators.longControlState == LongCtrlState.stopping
# TODO: look into using the actuators packet to send the desired speed
can_sends.append(fordcan.create_acc_msg(self.packer, self.CAN, CC.longActive, gas, accel, stopping, v_ego_kph=V_CRUISE_MAX))
### ui ###
+13 -11
View File
@@ -3,7 +3,7 @@ from opendbc.can.can_define import CANDefine
from opendbc.can.parser import CANParser
from openpilot.common.conversions import Conversions as CV
from openpilot.selfdrive.car.ford.fordcan import CanBus
from openpilot.selfdrive.car.ford.values import DBC, CarControllerParams, FordFlags, BUTTON_STATES
from openpilot.selfdrive.car.ford.values import DBC, CarControllerParams, FordFlags, BUTTONS
from openpilot.selfdrive.car.interfaces import CarStateBase
GearShifter = car.CarState.GearShifter
@@ -24,15 +24,14 @@ class CarState(CarStateBase):
self.lkas_enabled = None
self.prev_lkas_enabled = None
self.buttonStates = BUTTON_STATES.copy()
self.buttonStatesPrev = BUTTON_STATES.copy()
self.button_states = {button.event_type: False for button in BUTTONS}
def update(self, cp, cp_cam):
ret = car.CarState.new_message()
self.prev_mads_enabled = self.mads_enabled
self.prev_lkas_enabled = self.lkas_enabled
self.buttonStatesPrev = self.buttonStates.copy()
# Occasionally on startup, the ABS module recalibrates the steering pinion offset, so we need to block engagement
# The vehicle usually recovers out of this state within a minute of normal driving
@@ -87,6 +86,16 @@ class CarState(CarStateBase):
else:
ret.gearShifter = GearShifter.drive
# Buttons
for button in BUTTONS:
state = (cp.vl[button.can_addr][button.can_msg] in button.values)
if self.button_states[button.event_type] != state:
event = car.CarState.ButtonEvent.new_message()
event.type = button.event_type
event.pressed = state
self.button_events.append(event)
self.button_states[button.event_type] = state
# safety
ret.stockFcw = bool(cp_cam.vl["ACCDATA_3"]["FcwVisblWarn_B_Rq"])
ret.stockAeb = bool(cp_cam.vl["ACCDATA_2"]["CmbbBrkDecel_B_Rq"])
@@ -112,13 +121,6 @@ class CarState(CarStateBase):
self.lkas_enabled = bool(cp.vl["Steering_Data_FD1"]["TjaButtnOnOffPress"])
self.buttonStates["accelCruise"] = bool(cp.vl["Steering_Data_FD1"]["CcAslButtnSetIncPress"])
self.buttonStates["decelCruise"] = bool(cp.vl["Steering_Data_FD1"]["CcAslButtnSetDecPress"])
self.buttonStates["cancel"] = bool(cp.vl["Steering_Data_FD1"]["CcAslButtnCnclPress"])
self.buttonStates["setCruise"] = bool(cp.vl["Steering_Data_FD1"]["CcAslButtnSetPress"])
self.buttonStates["resumeCruise"] = bool(cp.vl["Steering_Data_FD1"]["CcAsllButtnResPress"])
self.buttonStates["gapAdjustCruise"] = bool(cp.vl["Steering_Data_FD1"]["AccButtnGapTogglePress"])
# Stock steering buttons so that we can passthru blinkers etc.
self.buttons_stock_values = cp.vl["Steering_Data_FD1"]
# Stock values from IPMA so that we can retain some stock functionality
+1 -1
View File
@@ -112,7 +112,7 @@ def create_lat_ctl2_msg(packer, CAN: CanBus, mode: int, path_offset: float, path
}
# calculate checksum
dat = packer.make_can_msg("LateralMotionControl2", 0, values)[2]
dat = packer.make_can_msg("LateralMotionControl2", 0, values)[1]
values["LatCtlPath_No_Cs"] = calculate_lat_ctl2_checksum(mode, counter, dat)
return packer.make_can_msg("LateralMotionControl2", CAN.main, values)
+14 -29
View File
@@ -1,9 +1,9 @@
from cereal import car
from panda import Panda
from openpilot.common.conversions import Conversions as CV
from openpilot.selfdrive.car import create_button_events, get_safety_config, create_mads_event
from openpilot.selfdrive.car import create_button_events, get_safety_config
from openpilot.selfdrive.car.ford.fordcan import CanBus
from openpilot.selfdrive.car.ford.values import Ecu, FordFlags, BUTTON_STATES
from openpilot.selfdrive.car.ford.values import Ecu, FordFlags
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
ButtonType = car.CarState.ButtonEvent.Type
@@ -15,8 +15,6 @@ class CarInterface(CarInterfaceBase):
def __init__(self, CP, CarController, CarState):
super().__init__(CP, CarController, CarState)
self.buttonStatesPrev = BUTTON_STATES.copy()
@staticmethod
def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs):
ret.carName = "ford"
@@ -74,34 +72,30 @@ class CarInterface(CarInterfaceBase):
def _update(self, c):
ret = self.CS.update(self.cp, self.cp_cam)
self.sp_update_params()
buttonEvents = create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise})
for button in self.CS.buttonStates:
if self.CS.buttonStates[button] != self.buttonStatesPrev[button]:
be = car.CarState.ButtonEvent.new_message()
be.type = button
be.pressed = self.CS.buttonStates[button]
buttonEvents.append(be)
self.CS.button_events = [
*self.CS.button_events,
*create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise}),
*create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}),
]
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
buttonEvents, c.vCruise)
self.CS.button_events, c.vCruise)
if ret.cruiseState.available:
if self.enable_mads:
if not self.CS.prev_mads_enabled and self.CS.mads_enabled:
self.CS.madsEnabled = True
if not self.CS.prev_lkas_enabled and self.CS.lkas_enabled:
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
self.CS.madsEnabled = not self.CS.madsEnabled
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
else:
self.CS.madsEnabled = False
if not self.CP.pcmCruise or (self.CP.pcmCruise and self.CP.minEnableSpeed > 0):
if any(b.type == ButtonType.cancel for b in buttonEvents):
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
if self.get_sp_pedal_disengage(ret):
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
@@ -114,16 +108,10 @@ class CarInterface(CarInterfaceBase):
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=bool(self.CS.distance_button))
if self.CS.out.madsEnabled != self.CS.madsEnabled:
if self.mads_event_lock:
buttonEvents.append(create_mads_event(self.mads_event_lock))
self.mads_event_lock = False
else:
if not self.mads_event_lock:
buttonEvents.append(create_mads_event(self.mads_event_lock))
self.mads_event_lock = True
ret.buttonEvents = buttonEvents
ret.buttonEvents = [
*self.CS.button_events,
*self.button_events.create_mads_event(self.CS.madsEnabled, self.CS.out.madsEnabled) # MADS BUTTON
]
events = self.create_common_events(ret, c, extra_gears=[GearShifter.manumatic], pcm_enable=False)
@@ -134,7 +122,4 @@ class CarInterface(CarInterfaceBase):
ret.events = events.to_msg()
# update previous car states
self.buttonStatesPrev = self.CS.buttonStates.copy()
return ret
+11 -10
View File
@@ -1,5 +1,6 @@
import copy
import re
from collections import namedtuple
from dataclasses import dataclass, field, replace
from enum import Enum, IntFlag
@@ -11,6 +12,7 @@ from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, Ca
from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, LiveFwVersions, OfflineFwVersions, Request, StdQueries, p16
Ecu = car.CarParams.Ecu
Button = namedtuple('Button', ['event_type', 'can_addr', 'can_msg', 'values'])
class CarControllerParams:
@@ -46,16 +48,6 @@ class FordFlags(IntFlag):
CANFD = 1
BUTTON_STATES = {
"accelCruise": False,
"decelCruise": False,
"cancel": False,
"setCruise": False,
"resumeCruise": False,
"gapAdjustCruise": False
}
class RADAR:
DELPHI_ESR = 'ford_fusion_2018_adas'
DELPHI_MRR = 'FORD_CADS'
@@ -154,6 +146,15 @@ class CAR(Platforms):
)
BUTTONS = [
Button(car.CarState.ButtonEvent.Type.accelCruise, "Steering_Data_FD1", "CcAslButtnSetIncPress", [1]),
Button(car.CarState.ButtonEvent.Type.decelCruise, "Steering_Data_FD1", "CcAslButtnSetDecPress", [1]),
Button(car.CarState.ButtonEvent.Type.cancel, "Steering_Data_FD1", "CcAslButtnCnclPress", [1]),
Button(car.CarState.ButtonEvent.Type.setCruise, "Steering_Data_FD1", "CcAslButtnSetPress", [1]),
Button(car.CarState.ButtonEvent.Type.resumeCruise, "Steering_Data_FD1", "CcAsllButtnResPress", [1]),
]
# FW response contains a combined software and part number
# A-Z except no I, O or W
# e.g. NZ6A-14C204-AAA
+2 -4
View File
@@ -1,9 +1,8 @@
from cereal import car
from openpilot.common.conversions import Conversions as CV
from openpilot.common.numpy_fast import interp
from openpilot.common.realtime import DT_CTRL
from opendbc.can.packer import CANPacker
from openpilot.selfdrive.car import apply_driver_steer_torque_limits
from openpilot.selfdrive.car import DT_CTRL, apply_driver_steer_torque_limits
from openpilot.selfdrive.car.gm import gmcan
from openpilot.selfdrive.car.gm.values import DBC, CanBus, CarControllerParams, CruiseButtons
from openpilot.selfdrive.car.interfaces import CarControllerBase
@@ -20,12 +19,11 @@ MIN_STEER_MSG_INTERVAL_MS = 15
class CarController(CarControllerBase):
def __init__(self, dbc_name, CP, VM):
self.CP = CP
super().__init__(dbc_name, CP, VM)
self.start_time = 0.
self.apply_steer_last = 0
self.apply_gas = 0
self.apply_brake = 0
self.frame = 0
self.last_steer_frame = 0
self.last_button_frame = 0
self.cancel_counter = 0
+1 -1
View File
@@ -64,7 +64,7 @@ def create_gas_regen_command(packer, bus, throttle, idx, enabled, at_full_stop):
"GasRegenAlwaysOne3": 1,
}
dat = packer.make_can_msg("ASCMGasRegenCmd", bus, values)[2]
dat = packer.make_can_msg("ASCMGasRegenCmd", bus, values)[1]
values["GasRegenChecksum"] = (((0xff - dat[1]) & 0xff) << 16) | \
(((0xff - dat[2]) & 0xff) << 8) | \
((0x100 - dat[3] - idx) & 0xff)
+15 -20
View File
@@ -6,11 +6,10 @@ from panda import Panda
from openpilot.common.basedir import BASEDIR
from openpilot.common.conversions import Conversions as CV
from openpilot.selfdrive.car import create_button_events, get_safety_config, create_mads_event
from openpilot.selfdrive.car import create_button_events, get_safety_config, get_friction
from openpilot.selfdrive.car.gm.radar_interface import RADAR_HEADER_MSG
from openpilot.selfdrive.car.gm.values import CAR, CruiseButtons, CarControllerParams, EV_CAR, CAMERA_ACC_CAR, CanBus
from openpilot.selfdrive.car.interfaces import CarInterfaceBase, TorqueFromLateralAccelCallbackType, FRICTION_THRESHOLD, LatControlInputs, NanoFFModel
from openpilot.selfdrive.controls.lib.drive_helpers import get_friction
ButtonType = car.CarState.ButtonEvent.Type
EventName = car.CarEvent.EventName
@@ -204,14 +203,12 @@ class CarInterface(CarInterfaceBase):
# returns a car.CarState
def _update(self, c):
ret = self.CS.update(self.cp, self.cp_cam, self.cp_loopback)
self.sp_update_params()
buttonEvents = []
distance_button = 0
# Don't add event if transitioning from INIT, unless it's to an actual button
if self.CS.cruise_buttons != CruiseButtons.UNPRESS or self.CS.prev_cruise_buttons != CruiseButtons.INIT:
buttonEvents = [
self.CS.button_events = [
*create_button_events(self.CS.cruise_buttons, self.CS.prev_cruise_buttons, BUTTONS_DICT,
unpressed_btn=CruiseButtons.UNPRESS),
*create_button_events(self.CS.distance_button, self.CS.prev_distance_button,
@@ -219,27 +216,32 @@ class CarInterface(CarInterfaceBase):
]
distance_button = self.CS.distance_button
self.CS.button_events = [
*self.CS.button_events,
*create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}),
]
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
if not self.CP.pcmCruise:
if any(b.type == ButtonType.accelCruise and b.pressed for b in buttonEvents):
if any(b.type == ButtonType.accelCruise and b.pressed for b in self.CS.button_events):
self.CS.accEnabled = True
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
buttonEvents, c.vCruise)
self.CS.button_events, c.vCruise)
if ret.cruiseState.available:
if self.enable_mads:
if not self.CS.prev_mads_enabled and self.CS.mads_enabled:
self.CS.madsEnabled = True
if self.CS.prev_lkas_enabled != 1 and self.CS.lkas_enabled == 1:
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
self.CS.madsEnabled = not self.CS.madsEnabled
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
else:
self.CS.madsEnabled = False
if not self.CP.pcmCruise or (self.CP.pcmCruise and self.CP.minEnableSpeed > 0):
if any(b.type == ButtonType.cancel for b in buttonEvents):
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
if self.get_sp_pedal_disengage(ret):
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
@@ -252,17 +254,10 @@ class CarInterface(CarInterfaceBase):
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=bool(distance_button))
# MADS BUTTON
if self.CS.out.madsEnabled != self.CS.madsEnabled:
if self.mads_event_lock:
buttonEvents.append(create_mads_event(self.mads_event_lock))
self.mads_event_lock = False
else:
if not self.mads_event_lock:
buttonEvents.append(create_mads_event(self.mads_event_lock))
self.mads_event_lock = True
ret.buttonEvents = buttonEvents
ret.buttonEvents = [
*self.CS.button_events,
*self.button_events.create_mads_event(self.CS.madsEnabled, self.CS.out.madsEnabled) # MADS BUTTON
]
# The ECM allows enabling on falling edge of set, but only rising edge of resume
events = self.create_common_events(ret, c, extra_gears=[GearShifter.sport, GearShifter.low,
+12 -21
View File
@@ -5,13 +5,12 @@ import cereal.messaging as messaging
from openpilot.common.conversions import Conversions as CV
from openpilot.common.numpy_fast import clip, interp
from openpilot.common.params import Params
from openpilot.common.realtime import DT_CTRL
from opendbc.can.packer import CANPacker
from openpilot.selfdrive.car import create_gas_interceptor_command
from openpilot.selfdrive.car import DT_CTRL, rate_limit, make_tester_present_msg, create_gas_interceptor_command
from openpilot.selfdrive.car.honda import hondacan
from openpilot.selfdrive.car.honda.values import CruiseButtons, VISUAL_HUD, HONDA_BOSCH, HONDA_BOSCH_RADARLESS, HONDA_NIDEC_ALT_PCM_ACCEL, CarControllerParams
from openpilot.selfdrive.car.interfaces import CarControllerBase
from openpilot.selfdrive.controls.lib.drive_helpers import rate_limit, HONDA_V_CRUISE_MIN
from openpilot.selfdrive.controls.lib.drive_helpers import HONDA_V_CRUISE_MIN
VisualAlert = car.CarControl.HUDControl.VisualAlert
LongCtrlState = car.CarControl.Actuators.LongControlState
@@ -110,11 +109,10 @@ def rate_limit_steer(new_steer, last_steer):
class CarController(CarControllerBase):
def __init__(self, dbc_name, CP, VM):
self.CP = CP
super().__init__(dbc_name, CP, VM)
self.packer = CANPacker(dbc_name)
self.params = CarControllerParams(CP)
self.CAN = hondacan.CanBus(CP)
self.frame = 0
self.braking = False
self.brake_steady = 0.
@@ -132,9 +130,6 @@ class CarController(CarControllerBase):
self.sm = messaging.SubMaster(['longitudinalPlanSP'])
self.param_s = Params()
self.is_metric = self.param_s.get_bool("IsMetric")
self.speed_limit_control_enabled = False
self.last_speed_limit_sign_tap = False
self.last_speed_limit_sign_tap_prev = False
self.speed_limit = 0.
self.speed_limit_offset = 0
@@ -173,11 +168,7 @@ class CarController(CarControllerBase):
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
if self.frame % 200 == 0:
self.speed_limit_control_enabled = self.param_s.get_bool("EnableSlc")
self.is_metric = self.param_s.get_bool("IsMetric")
self.last_speed_limit_sign_tap = self.param_s.get_bool("LastSpeedLimitSignTap")
self.v_cruise_min = HONDA_V_CRUISE_MIN[self.is_metric] * (CV.KPH_TO_MPH if not self.is_metric else 1)
self.v_cruise_min = HONDA_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
actuators = CC.actuators
hud_control = CC.hudControl
@@ -213,14 +204,14 @@ class CarController(CarControllerBase):
self.params.STEER_LOOKUP_BP, self.params.STEER_LOOKUP_V))
if not self.CP.pcmCruiseSpeed:
if not self.last_speed_limit_sign_tap_prev and self.last_speed_limit_sign_tap:
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
self.sl_force_active_timer = self.frame
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
self.last_speed_limit_sign_tap_prev = self.last_speed_limit_sign_tap
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
sl_force_active = self.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
sl_inactive = not sl_force_active and (not self.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
sl_temp_inactive = not sl_force_active and (self.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
slc_active = not sl_inactive and not sl_temp_inactive
self.slc_active_stock = slc_active
@@ -231,7 +222,7 @@ class CarController(CarControllerBase):
# tester present - w/ no response (keeps radar disabled)
if self.CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS) and self.CP.openpilotLongitudinalControl:
if self.frame % 10 == 0:
can_sends.append((0x18DAB0F1, 0, b"\x02\x3E\x80\x00\x00\x00\x00\x00", 1))
can_sends.append(make_tester_present_msg(0x18DAB0F1, 1, suppress_response=True))
# Send steering command.
can_sends.append(hondacan.create_steering_control(self.packer, self.CAN, apply_steer, CC.latActive, self.CP.carFingerprint,
@@ -432,8 +423,8 @@ class CarController(CarControllerBase):
return min(target_speed_kph, curve_speed)
def get_button_control(self, CS, final_speed, v_cruise_kph_prev):
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not self.is_metric else 1))
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not self.is_metric else CV.MS_TO_KPH))
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1))
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not CS.params_list.is_metric else CV.MS_TO_KPH))
cruise_button = self.get_button_type(self.button_type)
return cruise_button
+1 -1
View File
@@ -242,7 +242,7 @@ class CarState(CarStateBase):
ret.brakePressed = (cp.vl["POWERTRAIN_DATA"]["BRAKE_PRESSED"] != 0) or self.brake_switch_active
ret.brake = cp.vl["VSA_STATUS"]["USER_BRAKE"]
ret.cruiseState.enabled = self.pcm_cruise_enabled = cp.vl["POWERTRAIN_DATA"]["ACC_STATUS"] != 0
ret.cruiseState.enabled = cp.vl["POWERTRAIN_DATA"]["ACC_STATUS"] != 0
ret.cruiseState.available = bool(cp.vl[self.main_on_sig_msg]["MAIN_ON"])
# Gets rid of Pedal Grinding noise when brake is pressed at slow speeds for some models
+1
View File
@@ -576,6 +576,7 @@ FW_VERSIONS = {
b'28102-5MX-A900\x00\x00',
b'28102-5MX-A910\x00\x00',
b'28102-5MX-C001\x00\x00',
b'28102-5MX-C610\x00\x00',
b'28102-5MX-C910\x00\x00',
b'28102-5MX-D001\x00\x00',
b'28102-5MX-D710\x00\x00',
+20 -18
View File
@@ -174,11 +174,6 @@ class CarInterface(CarInterfaceBase):
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 239], [0, 239]]
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.,20], [0.,20]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.4,0.3], [0,0]]
tire_stiffness_factor = 0.8467
ret.longitudinalTuning.kpBP = [0., 5., 35.]
ret.longitudinalTuning.kpV = [2.4, 1.6, 0.8]
ret.longitudinalTuning.kiBP = [0., 35.]
ret.longitudinalTuning.kiV = [0.2, 0.16]
elif candidate in (CAR.HONDA_ODYSSEY, CAR.HONDA_ODYSSEY_CHN):
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.28], [0.08]]
@@ -266,9 +261,8 @@ class CarInterface(CarInterfaceBase):
# returns a car.CarState
def _update(self, c):
ret = self.CS.update(self.cp, self.cp_cam, self.cp_body)
self.sp_update_params()
buttonEvents = [
self.CS.button_events = [
*create_button_events(self.CS.cruise_buttons, self.CS.prev_cruise_buttons, BUTTONS_DICT),
*create_button_events(self.CS.cruise_setting, self.CS.prev_cruise_setting, SETTINGS_BUTTONS_DICT),
]
@@ -276,35 +270,43 @@ class CarInterface(CarInterfaceBase):
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
buttonEvents, c.vCruise)
self.CS.button_events, c.vCruise)
if ret.cruiseState.available:
if self.enable_mads:
if not self.CS.prev_mads_enabled and self.CS.mads_enabled:
self.CS.madsEnabled = True
if self.CS.prev_cruise_setting != 1 and self.CS.cruise_setting == 1:
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
self.CS.madsEnabled = not self.CS.madsEnabled
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
else:
self.CS.madsEnabled = False
if not self.CP.pcmCruise or (self.CP.pcmCruise and self.CP.minEnableSpeed > 0) or not self.CP.pcmCruiseSpeed:
if any(b.type == ButtonType.cancel for b in buttonEvents):
min_enable_speed_pcm = self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed
if not self.CP.pcmCruise or min_enable_speed_pcm or not self.CP.pcmCruiseSpeed:
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
if self.get_sp_pedal_disengage(ret):
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads else False if self.CP.pcmCruise else self.CS.accEnabled
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads or min_enable_speed_pcm \
else False if self.CP.pcmCruise \
else self.CS.accEnabled
if self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed:
if min_enable_speed_pcm:
if ret.gasPressed and not ret.cruiseState.enabled:
self.CS.accEnabled = False
self.CS.accEnabled = self.CS.pcm_cruise_enabled
if ret.cruiseState.enabled and not self.CS.out.cruiseState.enabled:
self.CS.accEnabled = True
elif not ret.cruiseState.enabled:
self.CS.accEnabled = False
ret, self.CS = self.get_sp_common_state(ret, self.CS,
min_enable_speed_pcm=(self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed),
gap_button=(self.CS.cruise_setting == 3))
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=(self.CS.cruise_setting == 3))
ret.buttonEvents = buttonEvents
ret.buttonEvents = [
*self.CS.button_events,
*self.button_events.create_mads_event(self.CS.madsEnabled, self.CS.out.madsEnabled) # MADS BUTTON
]
# events
events = self.create_common_events(ret, c, extra_gears=[GearShifter.sport, GearShifter.low], pcm_enable=False)
+13 -22
View File
@@ -3,9 +3,8 @@ import cereal.messaging as messaging
from openpilot.common.conversions import Conversions as CV
from openpilot.common.numpy_fast import clip
from openpilot.common.params import Params
from openpilot.common.realtime import DT_CTRL
from opendbc.can.packer import CANPacker
from openpilot.selfdrive.car import apply_driver_steer_torque_limits, common_fault_avoidance
from openpilot.selfdrive.car import DT_CTRL, apply_driver_steer_torque_limits, common_fault_avoidance, make_tester_present_msg
from openpilot.selfdrive.car.hyundai import hyundaicanfd, hyundaican
from openpilot.selfdrive.car.hyundai.hyundaicanfd import CanBus
from openpilot.selfdrive.car.hyundai.values import HyundaiFlags, HyundaiFlagsSP, Buttons, CarControllerParams, CANFD_CAR, CAR, CAMERA_SCC_CAR, LEGACY_SAFETY_MODE_CAR
@@ -48,12 +47,11 @@ def process_hud_alert(enabled, fingerprint, hud_control):
class CarController(CarControllerBase):
def __init__(self, dbc_name, CP, VM):
self.CP = CP
super().__init__(dbc_name, CP, VM)
self.CAN = CanBus(CP)
self.params = CarControllerParams(CP)
self.packer = CANPacker(dbc_name)
self.angle_limit_counter = 0
self.frame = 0
self.accel_last = 0
self.apply_steer_last = 0
@@ -72,9 +70,6 @@ class CarController(CarControllerBase):
self.sm = messaging.SubMaster(sub_services)
self.param_s = Params()
self.is_metric = self.param_s.get_bool("IsMetric")
self.speed_limit_control_enabled = False
self.last_speed_limit_sign_tap = False
self.last_speed_limit_sign_tap_prev = False
self.speed_limit = 0.
self.speed_limit_offset = 0
@@ -127,11 +122,7 @@ class CarController(CarControllerBase):
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
if self.frame % 200 == 0:
self.speed_limit_control_enabled = self.param_s.get_bool("EnableSlc")
self.is_metric = self.param_s.get_bool("IsMetric")
self.last_speed_limit_sign_tap = self.param_s.get_bool("LastSpeedLimitSignTap")
self.v_cruise_min = HYUNDAI_V_CRUISE_MIN[self.is_metric] * (CV.KPH_TO_MPH if not self.is_metric else 1)
self.v_cruise_min = HYUNDAI_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
actuators = CC.actuators
hud_control = CC.hudControl
@@ -175,14 +166,14 @@ class CarController(CarControllerBase):
blinking_icon = (self.frame - self.disengage_blink) * DT_CTRL < 1.0 if self.lat_disengage_init else False
if not self.CP.pcmCruiseSpeed:
if not self.last_speed_limit_sign_tap_prev and self.last_speed_limit_sign_tap:
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
self.sl_force_active_timer = self.frame
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
self.last_speed_limit_sign_tap_prev = self.last_speed_limit_sign_tap
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
sl_force_active = self.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
sl_inactive = not sl_force_active and (not self.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
sl_temp_inactive = not sl_force_active and (self.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
slc_active = not sl_inactive and not sl_temp_inactive
self.slc_active_stock = slc_active
@@ -202,11 +193,11 @@ class CarController(CarControllerBase):
addr, bus = 0x7d0, 0
if self.CP.flags & HyundaiFlags.CANFD_HDA2.value:
addr, bus = 0x730, self.CAN.ECAN
can_sends.append([addr, 0, b"\x02\x3E\x80\x00\x00\x00\x00\x00", bus])
can_sends.append(make_tester_present_msg(addr, bus, suppress_response=True))
# for blinkers
if self.CP.flags & HyundaiFlags.ENABLE_BLINKERS:
can_sends.append([0x7b1, 0, b"\x02\x3E\x80\x00\x00\x00\x00\x00", self.CAN.ECAN])
can_sends.append(make_tester_present_msg(0x7b1, self.CAN.ECAN, suppress_response=True))
# CAN-FD platforms
if self.CP.carFingerprint in CANFD_CAR:
@@ -235,7 +226,7 @@ class CarController(CarControllerBase):
if hda2:
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
if self.frame % 2 == 0:
can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CC.enabled and CS.out.cruiseState.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CS, CC.enabled and CS.out.cruiseState.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
set_speed_in_units, hud_control))
self.accel_last = accel
else:
@@ -433,8 +424,8 @@ class CarController(CarControllerBase):
return min(target_speed_kph, curve_speed)
def get_button_control(self, CS, final_speed, v_cruise_kph_prev):
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not self.is_metric else 1))
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not self.is_metric else CV.MS_TO_KPH))
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1))
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not CS.params_list.is_metric else CV.MS_TO_KPH))
cruise_button = self.get_button_type(self.button_type)
return cruise_button
+10 -7
View File
@@ -62,6 +62,11 @@ class CarState(CarStateBase):
self.escc_aeb_dec_cmd = 0
self._speed_limit_clu = 0
def get_main_enabled(self, ret) -> bool:
if self.prev_main_buttons != 1 and self.main_buttons[-1] == 1:
self.mainEnabled = not self.mainEnabled
return ret.cruiseState.available and self.mainEnabled
def update(self, cp, cp_cam):
if self.CP.carFingerprint in CANFD_CAR:
return self.update_canfd(cp, cp_cam)
@@ -112,7 +117,7 @@ class CarState(CarStateBase):
# cruise state
if self.CP.openpilotLongitudinalControl:
# These are not used for engage/disengage since openpilot keeps track of state using the buttons
ret.cruiseState.available = cp.vl["TCS13"]["ACCEnable"] == 0 and self.mainEnabled
ret.cruiseState.available = cp.vl["TCS13"]["ACCEnable"] == 0
ret.cruiseState.enabled = cp.vl["TCS13"]["ACC_REQ"] == 1
ret.cruiseState.standstill = False
ret.cruiseState.nonAdaptive = False
@@ -207,17 +212,12 @@ class CarState(CarStateBase):
self.cruise_buttons.extend(cp.vl_all["CLU11"]["CF_Clu_CruiseSwState"])
self.main_buttons.extend(cp.vl_all["CLU11"]["CF_Clu_CruiseSwMain"])
if self.CP.openpilotLongitudinalControl:
if self.prev_main_buttons != 1:
if self.main_buttons[-1] == 1:
self.mainEnabled = not self.mainEnabled
ret.cruiseState.available = ret.cruiseState.available and self.mainEnabled
ret.cruiseState.available = self.get_main_enabled(ret)
self.prev_mads_enabled = self.mads_enabled
self.prev_lfa_enabled = self.lfa_enabled
if self.CP.spFlags & HyundaiFlagsSP.SP_CAN_LFA_BTN:
self.lfa_enabled = cp.vl["BCM_PO_11"]["LFA_Pressed"]
self.mads_enabled = False if not self.control_initialized else ret.cruiseState.available
if self.CP.spFlags & HyundaiFlagsSP.SP_NAV_MSG or self.CP.spFlags & HyundaiFlagsSP.SP_LKAS12:
self._update_traffic_signals(cp, cp_cam)
ret.cruiseState.speedLimit = self._calculate_speed_limit() * speed_conv
@@ -282,6 +282,7 @@ class CarState(CarStateBase):
ret.cruiseState.standstill = False
else:
cp_cruise_info = cp_cam if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else cp
ret.cruiseState.available = cp_cruise_info.vl["SCC_CONTROL"]["MainMode_ACC"] == 1
ret.cruiseState.enabled = cp_cruise_info.vl["SCC_CONTROL"]["ACCMode"] in (1, 2)
ret.cruiseState.standstill = cp_cruise_info.vl["SCC_CONTROL"]["CRUISE_STANDSTILL"] == 1
ret.cruiseState.speed = cp_cruise_info.vl["SCC_CONTROL"]["VSetDis"] * speed_factor
@@ -298,6 +299,8 @@ class CarState(CarStateBase):
self.prev_main_buttons = self.main_buttons[-1]
self.cruise_buttons.extend(cp.vl_all[self.cruise_btns_msg_canfd]["CRUISE_BUTTONS"])
self.main_buttons.extend(cp.vl_all[self.cruise_btns_msg_canfd]["ADAPTIVE_CRUISE_MAIN_BTN"])
if self.CP.openpilotLongitudinalControl:
ret.cruiseState.available = self.get_main_enabled(ret)
self.prev_mads_enabled = self.mads_enabled
self.prev_lfa_enabled = self.lfa_enabled
self.lfa_enabled = cp.vl[self.cruise_btns_msg_canfd]["LFA_BTN"]
+10
View File
@@ -171,6 +171,7 @@ FW_VERSIONS = {
(Ecu.eps, 0x7d4, None): [
b'\xf1\x00DN8 MDPS C 1,00 1,01 56310L0010\x00 4DNAC101',
b'\xf1\x00DN8 MDPS C 1.00 1.01 56310-L0010 4DNAC101',
b'\xf1\x00DN8 MDPS C 1.00 1.01 56310-L0200 4DNAC102',
b'\xf1\x00DN8 MDPS C 1.00 1.01 56310-L0210 4DNAC101',
b'\xf1\x00DN8 MDPS C 1.00 1.01 56310-L0210 4DNAC102',
b'\xf1\x00DN8 MDPS C 1.00 1.01 56310L0010\x00 4DNAC101',
@@ -291,6 +292,7 @@ FW_VERSIONS = {
b'\xf1\x00TM MDPS C 1.00 1.02 56310-CLAC0 4TSHC102',
b'\xf1\x00TM MDPS C 1.00 1.02 56310-CLEC0 4TSHC102',
b'\xf1\x00TM MDPS C 1.00 1.02 56310-GA000 4TSHA100',
b'\xf1\x00TM MDPS C 1.00 1.02 56310GA000\x00 4TSHA100',
b'\xf1\x00TM MDPS R 1.00 1.05 57700-CL000 4TSHP105',
b'\xf1\x00TM MDPS R 1.00 1.06 57700-CL000 4TSHP106',
],
@@ -407,6 +409,7 @@ FW_VERSIONS = {
b'\xf1\x00ON ESC \x0b 100\x18\x12\x18 58910-S9360',
b'\xf1\x00ON ESC \x0b 101\x19\t\x05 58910-S9320',
b'\xf1\x00ON ESC \x0b 101\x19\t\x08 58910-S9360',
b'\xf1\x00ON ESC \x0b 103$\x04\x08 58910-S9360',
],
(Ecu.eps, 0x7d4, None): [
b'\xf1\x00LX2 MDPS C 1,00 1,03 56310-S8020 4LXDC103',
@@ -480,11 +483,13 @@ FW_VERSIONS = {
},
CAR.GENESIS_G80: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00DH__ SCC F-CU- 1.00 1.01 96400-B1110 ',
b'\xf1\x00DH__ SCC F-CUP 1.00 1.01 96400-B1120 ',
b'\xf1\x00DH__ SCC F-CUP 1.00 1.02 96400-B1120 ',
b'\xf1\x00DH__ SCC FHCUP 1.00 1.01 96400-B1110 ',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00DH LKAS AT EUR LHD 1.01 1.01 95895-B1500 161014',
b'\xf1\x00DH LKAS AT KOR LHD 1.01 1.01 95895-B1500 161014',
b'\xf1\x00DH LKAS AT KOR LHD 1.01 1.02 95895-B1500 170810',
b'\xf1\x00DH LKAS AT USA LHD 1.01 1.01 95895-B1500 161014',
@@ -585,6 +590,7 @@ FW_VERSIONS = {
b'\xf1\x00DL3 MDPS C 1.00 1.02 56310-L7220 4DLHC102',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00DL3HMFC AT KOR LHD 1.00 1.01 99210-L2000 191022',
b'\xf1\x00DL3HMFC AT KOR LHD 1.00 1.02 99210-L2000 200309',
b'\xf1\x00DL3HMFC AT KOR LHD 1.00 1.04 99210-L2000 210527',
],
@@ -595,6 +601,7 @@ FW_VERSIONS = {
b'\xf1\x00OS IEB \x02 210 \x02\x14 58520-K4000',
b'\xf1\x00OS IEB \x02 212 \x11\x13 58520-K4000',
b'\xf1\x00OS IEB \x03 210 \x02\x14 58520-K4000',
b'\xf1\x00OS IEB \x03 211 \x04\x02 58520-K4000',
b'\xf1\x00OS IEB \x03 212 \x11\x13 58520-K4000',
b'\xf1\x00OS IEB \r 105\x18\t\x18 58520-K4000',
],
@@ -705,6 +712,7 @@ FW_VERSIONS = {
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00DEhe SCC F-CUP 1.00 1.02 99110-G5100 ',
b'\xf1\x00DEhe SCC FHCUP 1.00 1.02 99110-G5100 ',
b'\xf1\x00DEhe SCC H-CUP 1.01 1.02 96400-G5100 ',
],
},
@@ -757,10 +765,12 @@ FW_VERSIONS = {
b'\xf1\x00JF__ SCC F-CUP 1.00 1.00 96400-D4100 ',
],
(Ecu.abs, 0x7d1, None): [
b'\xf1\x00JF ESC \t 17 \x16\x06# 58920-D4180',
b'\xf1\x00JF ESC \x0f 16 \x16\x06\x17 58920-D5080',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00JFWGN LDWS AT USA LHD 1.00 1.02 95895-D4100 G21',
b'\xf1\x00JFWGN LKAS AT EUR LHD 1.00 1.01 95895-D4100 G20',
],
},
CAR.KIA_OPTIMA_G4_FL: {
+3 -3
View File
@@ -81,7 +81,7 @@ def create_lkas11(packer, frame, CP, apply_steer, steer_req,
# Genesis and Optima fault when forwarding while engaged
values["CF_Lkas_LdwsActivemode"] = 2
dat = packer.make_can_msg("LKAS11", 0, values)[2]
dat = packer.make_can_msg("LKAS11", 0, values)[1]
if CP.flags & HyundaiFlags.CHECKSUM_CRC8:
# CRC Checksum as seen on 2019 Hyundai Santa Fe
@@ -166,7 +166,7 @@ def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, se
scc12_values["CF_VSM_DecCmdAct"] = CS.escc_aeb_dec_cmd_act
scc12_values["CR_VSM_DecCmd"] = CS.escc_aeb_dec_cmd
scc12_dat = packer.make_can_msg("SCC12", 0, scc12_values)[2]
scc12_dat = packer.make_can_msg("SCC12", 0, scc12_values)[1]
scc12_values["CR_VSM_ChkSum"] = 0x10 - sum(sum(divmod(i, 16)) for i in scc12_dat) % 0x10
commands.append(packer.make_can_msg("SCC12", 0, scc12_values))
@@ -197,7 +197,7 @@ def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, se
"FCA_DrvSetStatus": 1,
"FCA_Status": 1, # AEB disabled
}
fca11_dat = packer.make_can_msg("FCA11", 0, fca11_values)[2]
fca11_dat = packer.make_can_msg("FCA11", 0, fca11_values)[1]
fca11_values["CR_FCA_ChkSum"] = hyundai_checksum(fca11_dat[:7])
commands.append(packer.make_can_msg("FCA11", 0, fca11_values))
+2 -2
View File
@@ -121,7 +121,7 @@ def create_lfahda_cluster(packer, CAN, enabled, lat_active, lateral_paused, blin
return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values)
def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control):
def create_acc_control(packer, CAN, CS, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control):
jerk = 5
jn = jerk / 50
if not enabled or gas_override:
@@ -132,7 +132,7 @@ def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_ov
values = {
"ACCMode": 0 if not enabled else (2 if gas_override else 1),
"MainMode_ACC": 1,
"MainMode_ACC": 1 if CS.mainEnabled else 0,
"StopReq": 1 if stopping else 0,
"aReqValue": a_val,
"aReqRaw": a_raw,
+26 -31
View File
@@ -7,7 +7,7 @@ from openpilot.selfdrive.car.hyundai.values import HyundaiFlags, HyundaiFlagsSP,
CANFD_UNSUPPORTED_LONGITUDINAL_CAR, NON_SCC_CAR, EV_CAR, HYBRID_CAR, LEGACY_SAFETY_MODE_CAR, \
UNSUPPORTED_LONGITUDINAL_CAR, Buttons
from openpilot.selfdrive.car.hyundai.radar_interface import RADAR_START_ADDR
from openpilot.selfdrive.car import create_button_events, get_safety_config, create_mads_event
from openpilot.selfdrive.car import create_button_events, get_safety_config
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
from openpilot.selfdrive.car.disable_ecu import disable_ecu
@@ -203,35 +203,37 @@ class CarInterface(CarInterfaceBase):
def _update(self, c):
ret = self.CS.update(self.cp, self.cp_cam)
self.sp_update_params()
buttonEvents = create_button_events(self.CS.cruise_buttons[-1], self.CS.prev_cruise_buttons, BUTTONS_DICT)
self.CS.button_events = [
*create_button_events(self.CS.cruise_buttons[-1], self.CS.prev_cruise_buttons, BUTTONS_DICT),
*create_button_events(self.CS.lfa_enabled, self.CS.prev_lfa_enabled, {1: ButtonType.altButton1}),
*create_button_events(self.CS.main_buttons[-1], self.CS.prev_main_buttons, {1: ButtonType.altButton3}),
]
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
buttonEvents, c.vCruise)
self.CS.mads_enabled = False if not self.mads_main_toggle else self.CS.mads_enabled
self.CS.button_events, c.vCruise)
if ret.cruiseState.available:
if not self.CP.pcmCruiseSpeed:
if self.CS.prev_main_buttons == 1:
if self.CS.main_buttons[-1] != 1:
self.CS.accEnabled = True
elif self.CS.prev_cruise_buttons == 4:
if self.CS.cruise_buttons[-1] != 4:
self.accEnabled = True
if self.enable_mads:
if not self.CS.prev_mads_enabled and self.CS.mads_enabled:
self.CS.madsEnabled = True
if self.CS.prev_lfa_enabled != 1 and self.CS.lfa_enabled == 1:
self.CS.madsEnabled = not self.CS.madsEnabled
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
else:
if any(b.type in (ButtonType.altButton3, ButtonType.cancel) and not b.pressed for b in self.CS.button_events):
self.CS.accEnabled = True
if self.enable_mads:
if not self.CS.prev_mads_enabled and self.CS.mads_enabled and \
any(b.type == ButtonType.altButton3 for b in self.CS.button_events):
self.CS.madsEnabled = True
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
self.CS.madsEnabled = not self.CS.madsEnabled
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
if not ret.cruiseState.available and self.CS.out.cruiseState.available:
self.CS.madsEnabled = False
if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed:
if not self.CP.pcmCruise:
if any(b.type == ButtonType.cancel for b in buttonEvents):
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
if not self.CP.pcmCruiseSpeed:
if not ret.cruiseState.enabled:
@@ -242,17 +244,10 @@ class CarInterface(CarInterfaceBase):
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=(self.CS.cruise_buttons[-1] == 3))
# MADS BUTTON
if self.CS.out.madsEnabled != self.CS.madsEnabled:
if self.mads_event_lock:
buttonEvents.append(create_mads_event(self.mads_event_lock))
self.mads_event_lock = False
else:
if not self.mads_event_lock:
buttonEvents.append(create_mads_event(self.mads_event_lock))
self.mads_event_lock = True
ret.buttonEvents = buttonEvents
ret.buttonEvents = [
*self.CS.button_events,
*self.button_events.create_mads_event(self.CS.madsEnabled, self.CS.out.madsEnabled) # MADS BUTTON
]
# On some newer model years, the CANCEL button acts as a pause/resume button based on the PCM state
# To avoid re-engaging when openpilot cancels, check user engagement intention via buttons
+35 -45
View File
@@ -1,3 +1,4 @@
import capnp
import json
import os
import numpy as np
@@ -6,6 +7,7 @@ import tomllib
from abc import abstractmethod, ABC
from difflib import SequenceMatcher
from enum import StrEnum
from types import SimpleNamespace
from typing import Any, NamedTuple
from collections.abc import Callable
from functools import cache
@@ -16,13 +18,15 @@ from openpilot.common.conversions import Conversions as CV
from openpilot.common.simple_kalman import KF1D, get_kalman_gain
from openpilot.common.numpy_fast import clip
from openpilot.common.params import Params
from openpilot.common.realtime import DT_CTRL
from openpilot.selfdrive.car import apply_hysteresis, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness, STD_CARGO_KG
from openpilot.selfdrive.car import DT_CTRL, apply_hysteresis, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness, get_friction, STD_CARGO_KG, \
ButtonEvents
from openpilot.selfdrive.car.param_manager import ParamManager
from openpilot.selfdrive.car.values import PLATFORMS
from openpilot.selfdrive.controls.lib.desire_helper import get_min_lateral_speed
from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, V_CRUISE_UNSET, get_friction
from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, V_CRUISE_UNSET
from openpilot.selfdrive.controls.lib.events import Events
from openpilot.selfdrive.controls.lib.vehicle_model import VehicleModel
from openpilot.selfdrive.pandad import can_capnp_to_list
ButtonType = car.CarState.ButtonEvent.Type
GearShifter = car.CarState.GearShifter
@@ -68,6 +72,7 @@ class LatControlInputs(NamedTuple):
aego: float
SendCan = tuple[int, bytes, int]
TorqueFromLateralAccelCallbackType = Callable[[LatControlInputs, car.CarParams.LateralTorqueTuning, float, float, bool, bool], float]
@@ -237,22 +242,14 @@ class CarInterfaceBase(ABC):
self.mads_ndlob = self.enable_mads and not self.mads_disengage_lateral_on_brake
self.gear_warning = 0
self.cruise_cancelled_btn = True
self.acc_mads_combo = self.param_s.get_bool("AccMadsCombo")
self.is_metric = self.param_s.get_bool("IsMetric")
self.below_speed_pause = self.param_s.get_bool("BelowSpeedPause")
self.pause_lateral_speed = int(self.param_s.get("PauseLateralSpeed", encoding="utf8"))
self.prev_acc_mads_combo = False
self.mads_event_lock = True
self.gap_button_counter = 0
self.experimental_mode_hold = False
self.experimental_mode = self.param_s.get_bool("ExperimentalMode")
self._frame = 0
self.reverse_dm_cam = self.param_s.get_bool("ReverseDmCam")
self.mads_main_toggle = self.param_s.get_bool("MadsCruiseMain")
self.lkas_toggle = self.param_s.get_bool("LkasToggle")
self.last_mads_init = 0.
self.madsEnabledInit = False
self.madsEnabledInitPrev = False
self.button_events = ButtonEvents()
self.lat_torque_nn_model = None
eps_firmware = str(next((fw.fwVersion for fw in CP.carFw if fw.ecu == "eps"), ""))
@@ -265,7 +262,7 @@ class CarInterfaceBase(ABC):
self.lat_torque_nn_model, _ = get_nn_model(_car, eps_firmware)
return self.lat_torque_nn_model is not None and self.param_s.get_bool("NNFF")
def apply(self, c: car.CarControl, now_nanos: int) -> tuple[car.CarControl.Actuators, list[tuple[int, int, bytes, int]]]:
def apply(self, c: car.CarControl, now_nanos: int) -> tuple[car.CarControl.Actuators, list[SendCan]]:
return self.CC.update(c, self.CS, now_nanos)
@staticmethod
@@ -419,11 +416,15 @@ class CarInterfaceBase(ABC):
def _update(self, c: car.CarControl) -> car.CarState:
pass
def update(self, c: car.CarControl, can_strings: list[bytes]) -> car.CarState:
def update(self, c: car.CarControl, can_strings: list[bytes], params_list: SimpleNamespace) -> car.CarState:
# parse can
can_list = can_capnp_to_list(can_strings)
for cp in self.can_parsers:
if cp is not None:
cp.update_strings(can_strings)
cp.update_strings(can_list)
self.CS.button_events = []
self.CS.params_list = params_list
# get CarState
ret = self._update(c)
@@ -460,18 +461,19 @@ class CarInterfaceBase(ABC):
events.add(EventName.doorOpen)
if cs_out.seatbeltUnlatched and cs_out.gearShifter != GearShifter.park:
events.add(EventName.seatbeltNotLatched)
if cs_out.gearShifter != GearShifter.drive and cs_out.gearShifter not in extra_gears and not \
(cs_out.gearShifter == GearShifter.unknown and self.gear_warning < int(0.5/DT_CTRL)):
if cs_out.gearShifter != GearShifter.drive and (extra_gears is None or
cs_out.gearShifter not in extra_gears) and not (cs_out.gearShifter == GearShifter.unknown and
self.gear_warning < int(0.5/DT_CTRL)):
if cs_out.vEgo < 5:
events.add(EventName.silentWrongGear)
else:
events.add(EventName.wrongGear)
if cs_out.gearShifter == GearShifter.reverse:
if not self.reverse_dm_cam and cs_out.vEgo < 5:
if not self.CS.params_list.reverse_dm_cam and cs_out.vEgo < 5:
events.add(EventName.spReverseGear)
elif cs_out.vEgo >= 5:
events.add(EventName.reverseGear)
if not cs_out.cruiseState.available:
if not cs_out.cruiseState.available and cs_out.cruiseState.enabled:
events.add(EventName.wrongCarMode)
if cs_out.espDisabled:
events.add(EventName.espDisabled)
@@ -549,7 +551,7 @@ class CarInterfaceBase(ABC):
return v_cruise != V_CRUISE_UNSET
def get_acc_mads(self, cruiseState_enabled, acc_enabled, mads_enabled):
if self.acc_mads_combo:
if self.CS.params_list.acc_mads_combo:
if not self.prev_acc_mads_combo and (cruiseState_enabled or acc_enabled):
mads_enabled = True
self.prev_acc_mads_combo = (cruiseState_enabled or acc_enabled)
@@ -589,7 +591,7 @@ class CarInterfaceBase(ABC):
def get_sp_cruise_main_state(self, cs_out, CS):
if not CS.control_initialized:
mads_enabled = False
elif not self.mads_main_toggle:
elif not self.CS.params_list.mads_main_toggle:
mads_enabled = False
else:
mads_enabled = cs_out.cruiseState.available
@@ -601,7 +603,7 @@ class CarInterfaceBase(ABC):
self.madsEnabledInit = False
self.madsEnabledInitPrev = False
return False
if not self.mads_main_toggle or self.prev_acc_mads_combo:
if not self.CS.params_list.mads_main_toggle or self.prev_acc_mads_combo:
return CS.madsEnabled
if not self.madsEnabledInit and CS.madsEnabled:
self.madsEnabledInit = True
@@ -616,9 +618,8 @@ class CarInterfaceBase(ABC):
else:
return CS.madsEnabled
def get_sp_common_state(self, cs_out, CS, min_enable_speed_pcm=False, gear_allowed=True, gap_button=False):
cs_out.cruiseState.enabled = CS.accEnabled if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed or min_enable_speed_pcm else \
cs_out.cruiseState.enabled
def get_sp_common_state(self, cs_out, CS, gear_allowed=True, gap_button=False):
cs_out.cruiseState.enabled = CS.accEnabled if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed else cs_out.cruiseState.enabled
if not self.enable_mads:
if cs_out.cruiseState.enabled and not CS.out.cruiseState.enabled:
@@ -629,9 +630,9 @@ class CarInterfaceBase(ABC):
if self.CP.openpilotLongitudinalControl:
self.toggle_exp_mode(gap_button)
lane_change_speed_min = get_min_lateral_speed(self.pause_lateral_speed, self.is_metric)
lane_change_speed_min = get_min_lateral_speed(self.CS.params_list.pause_lateral_speed, self.CS.params_list.is_metric)
cs_out.belowLaneChangeSpeed = cs_out.vEgo < lane_change_speed_min and self.below_speed_pause
cs_out.belowLaneChangeSpeed = cs_out.vEgo < lane_change_speed_min and self.CS.params_list.below_speed_pause
if cs_out.gearShifter in [GearShifter.park, GearShifter.reverse] or cs_out.doorOpen or \
(cs_out.seatbeltUnlatched and cs_out.gearShifter != GearShifter.park):
@@ -664,7 +665,7 @@ class CarInterfaceBase(ABC):
if self.gap_button_counter > 50:
self.gap_button_counter = 0
self.experimental_mode_hold = True
self.param_s.put_bool_nonblocking("ExperimentalMode", not self.experimental_mode)
self.param_s.put_bool_nonblocking("ExperimentalMode", not self.CS.params_list.experimental_mode)
else:
self.gap_button_counter = 0
self.experimental_mode_hold = False
@@ -730,19 +731,9 @@ class CarInterfaceBase(ABC):
return events, cs_out
def sp_update_params(self):
self.experimental_mode = self.param_s.get_bool("ExperimentalMode")
self._frame += 1
if self._frame % 100 == 0:
self.is_metric = self.param_s.get_bool("IsMetric")
self.below_speed_pause = self.param_s.get_bool("BelowSpeedPause")
self.pause_lateral_speed = int(self.param_s.get("PauseLateralSpeed", encoding="utf8"))
if self._frame % 300 == 0:
self._frame = 0
self.reverse_dm_cam = self.param_s.get_bool("ReverseDmCam")
class RadarInterfaceBase(ABC):
def __init__(self, CP):
self.CP = CP
self.rcp = None
self.pts = {}
self.delay = 0
@@ -771,14 +762,15 @@ class CarStateBase(ABC):
self.cluster_speed_hyst_gap = 0.0
self.cluster_min_speed = 0.0 # min speed before dropping to 0
self.param_s = Params()
self.accEnabled = False
self.madsEnabled = False
self.disengageByBrake = False
self.mads_enabled = False
self.prev_mads_enabled = False
self.control_initialized = False
self.pcm_cruise_enabled = False
self.button_events: list[capnp.lib.capnp._DynamicStructBuilder] = []
self.params_list: SimpleNamespace = ParamManager().get_params()
Q = [[0.0, 0.0], [0.0, 100.0]]
R = 0.3
@@ -879,12 +871,10 @@ class CarStateBase(ABC):
return None
SendCan = tuple[int, int, bytes, int]
class CarControllerBase(ABC):
def __init__(self, dbc_name: str, CP, VM):
pass
self.CP = CP
self.frame = 0
@abstractmethod
def update(self, CC: car.CarControl.Actuators, CS: car.CarState, now_nanos: int) -> tuple[car.CarControl.Actuators, list[SendCan]]:

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