mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-06-10 11:14:19 +08:00
Compare commits
3 Commits
master-dev
...
archive/pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cb85c6d7d | ||
|
|
84c3668c3a | ||
|
|
89005e08c4 |
2
.github/labeler.yaml
vendored
2
.github/labeler.yaml
vendored
@@ -44,7 +44,7 @@ subaru:
|
||||
|
||||
tesla:
|
||||
- changed-files:
|
||||
- any-glob-to-all-files: 'selfdrive/car/tesla/*'
|
||||
- any-glob-to-all-files: 'selfdrive/car/telsa/*'
|
||||
|
||||
toyota:
|
||||
- changed-files:
|
||||
|
||||
2
.github/workflows/badges.yaml
vendored
2
.github/workflows/badges.yaml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
env:
|
||||
BASE_IMAGE: openpilot-base
|
||||
DOCKER_REGISTRY: ghcr.io/commaai
|
||||
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $DOCKER_REGISTRY/$BASE_IMAGE:latest /bin/bash -c
|
||||
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
|
||||
|
||||
jobs:
|
||||
badges:
|
||||
|
||||
104
.github/workflows/ci_weekly_report.yaml
vendored
104
.github/workflows/ci_weekly_report.yaml
vendored
@@ -10,30 +10,38 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
CI_RUNS: ${{ github.event.inputs.ci_runs || '50' }}
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
if: github.repository == 'commaai/openpilot'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ci_runs: ${{ steps.ci_runs_setup.outputs.matrix }}
|
||||
ci_runs: ${{ steps.ci_runs_setup.outputs.value }}
|
||||
steps:
|
||||
- id: ci_runs_setup
|
||||
name: CI_RUNS=${{ env.CI_RUNS }}
|
||||
run: |
|
||||
matrix=$(python3 -c "import json; print(json.dumps({ 'run_number' : list(range(${{ env.CI_RUNS }})) }))")
|
||||
echo "matrix=$matrix" >> $GITHUB_OUTPUT
|
||||
CI_RUNS=${{ inputs.ci_runs || '50' }}
|
||||
mylist="value=["
|
||||
|
||||
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: ${{fromJSON(needs.setup.outputs.ci_runs)}}
|
||||
matrix:
|
||||
value: ${{fromJSON(needs.setup.outputs.ci_runs)}}
|
||||
uses: commaai/openpilot/.github/workflows/ci_weekly_run.yaml@master
|
||||
with:
|
||||
run_number: ${{ matrix.run_number }}
|
||||
run_number: ${{ matrix.value }}
|
||||
|
||||
report:
|
||||
needs: [ci_matrix_run]
|
||||
@@ -54,48 +62,62 @@ jobs:
|
||||
})
|
||||
var report = {}
|
||||
jobs.slice(1, jobs.length-1).forEach(job => {
|
||||
if (job.conclusion === "skipped") return;
|
||||
const jobName = job.name.split(" / ")[2];
|
||||
const runRegex = /\((.*?)\)/;
|
||||
const run = job.name.match(runRegex)[1];
|
||||
const jobName = job.name.split('/')[2].trim();
|
||||
report[jobName] = report[jobName] || { successes: [], failures: [], cancelled: [] };
|
||||
switch (job.conclusion) {
|
||||
case "success":
|
||||
report[jobName].successes.push({ "run_number": run, "link": job.html_url}); break;
|
||||
report[jobName].successes.push(job.html_url); break;
|
||||
case "failure":
|
||||
report[jobName].failures.push({ "run_number": run, "link": job.html_url }); break;
|
||||
report[jobName].failures.push(job.html_url); break;
|
||||
case "cancelled":
|
||||
report[jobName].cancelled.push({ "run_number": run, "link": job.html_url }); break;
|
||||
report[jobName].cancelled.push(job.html_url); break;
|
||||
}
|
||||
});
|
||||
return JSON.stringify({"jobs": report});
|
||||
return JSON.stringify(report);
|
||||
|
||||
- name: Add job results to summary
|
||||
env:
|
||||
JOB_RESULTS: ${{ fromJSON(steps.get-job-results.outputs.result) }}
|
||||
run: |
|
||||
cat <<EOF >> template.html
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Job</th>
|
||||
<th>✅ Passing</th>
|
||||
<th>❌ Failure Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for key in jobs.keys() %}<tr>
|
||||
<td>{% for i in range(5) %}{% if i+1 <= (5 * jobs[key]["successes"]|length // ${{ env.CI_RUNS }}) %}🟩{% else %}🟥{% endif %}{% endfor%}</td>
|
||||
<td>{{ key }}</td>
|
||||
<td>{{ 100 * jobs[key]["successes"]|length // ${{ env.CI_RUNS }} }}%</td>
|
||||
<td>{% if jobs[key]["failures"]|length > 0 %}<details>{% for failure in jobs[key]["failures"] %}<a href="{{ failure['link'] }}">Log for run #{{ failure['run_number'] }}</a><br>{% endfor %}</details>{% else %}{% endif %}</td>
|
||||
</td>
|
||||
</tr>{% endfor %}
|
||||
</table>
|
||||
EOF
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
30
.github/workflows/docs.yaml
vendored
30
.github/workflows/docs.yaml
vendored
@@ -15,24 +15,31 @@ 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: 1
|
||||
timeout-minutes: 45
|
||||
if: false # TODO: replace this with the new docs
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
# Build
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
- name: Build openpilot
|
||||
run: |
|
||||
${{ env.RUN }} "scons -j$(nproc)"
|
||||
- name: Build docs
|
||||
run: |
|
||||
# TODO: can we install just the "docs" dependency group without the normal deps?
|
||||
pip install mkdocs
|
||||
mkdocs build
|
||||
${{ env.RUN }} "apt update && apt install -y doxygen && cd docs && make -j$(nproc) html"
|
||||
|
||||
# Push to docs.comma.ai
|
||||
- uses: actions/checkout@v4
|
||||
if: github.ref == 'refs/heads/master' && github.repository == 'commaai/openpilot'
|
||||
with:
|
||||
@@ -47,17 +54,16 @@ jobs:
|
||||
source release/identity.sh
|
||||
|
||||
cd openpilot-docs
|
||||
|
||||
git checkout --orphan tmp
|
||||
git rm -rf .
|
||||
|
||||
# copy over docs
|
||||
cp -r ../docs_site/ docs/
|
||||
|
||||
# GitHub pages config
|
||||
cp -r ../build/docs/html/ docs/
|
||||
cp -r ../docs/README.md .
|
||||
touch docs/.nojekyll
|
||||
echo -n docs.comma.ai > docs/CNAME
|
||||
|
||||
git add -f .
|
||||
|
||||
git commit -m "build docs"
|
||||
|
||||
# docs live in different repo to not bloat openpilot's full clone size
|
||||
|
||||
45
.github/workflows/jenkins-pr-trigger.yaml
vendored
45
.github/workflows/jenkins-pr-trigger.yaml
vendored
@@ -1,45 +0,0 @@
|
||||
name: jenkins scan
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created, edited]
|
||||
|
||||
jobs:
|
||||
# TODO: gc old branches in a separate job in this workflow
|
||||
scan-comments:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.issue.pull_request }}
|
||||
steps:
|
||||
- name: Check for trigger phrase
|
||||
id: check_comment
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const triggerPhrase = "trigger-jenkins";
|
||||
const comment = context.payload.comment.body;
|
||||
const commenter = context.payload.comment.user.login;
|
||||
|
||||
const { data: permissions } = await github.rest.repos.getCollaboratorPermissionLevel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
username: commenter
|
||||
});
|
||||
|
||||
const hasWriteAccess = permissions.permission === 'write' || permissions.permission === 'admin';
|
||||
|
||||
return (hasWriteAccess && comment.includes(triggerPhrase));
|
||||
result-encoding: json
|
||||
|
||||
- name: Checkout repository
|
||||
if: steps.check_comment.outputs.result == 'true'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: refs/pull/${{ github.event.issue.number }}/head
|
||||
|
||||
- name: Push to tmp-jenkins branch
|
||||
if: steps.check_comment.outputs.result == 'true'
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git checkout -b tmp-jenkins-${{ github.event.issue.number }}
|
||||
GIT_LFS_SKIP_PUSH=1 git push -f origin tmp-jenkins-${{ github.event.issue.number }}
|
||||
15
.github/workflows/mirror_to_gitlab.yaml
vendored
15
.github/workflows/mirror_to_gitlab.yaml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
git config --global user.email 'action@github.com'
|
||||
|
||||
- name: Set up SSH
|
||||
uses: webfactory/ssh-agent@v0.9.0
|
||||
uses: webfactory/ssh-agent@v0.5.3
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
||||
@@ -37,10 +37,19 @@ jobs:
|
||||
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: |
|
||||
git lfs pull
|
||||
|
||||
# Add GitLab remote
|
||||
git remote add gitlab git@gitlab.com:sunnypilot/sunnyhaibin/sunnypilot-github-mirror.git
|
||||
git push -u --force gitlab ${{ github.ref }}
|
||||
|
||||
# Fetch from GitLab and check if the branch exists
|
||||
if git fetch gitlab ${{ github.ref }}; then
|
||||
# Merge changes from GitLab if the branch exists
|
||||
git merge gitlab/${{ github.ref_name }} --allow-unrelated-histories --strategy-option=theirs
|
||||
else
|
||||
echo "Branch does not exist on GitLab, skipping merge."
|
||||
fi
|
||||
git push -u gitlab ${{ github.ref }} # 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
|
||||
8
.github/workflows/repo-maintenance.yaml
vendored
8
.github/workflows/repo-maintenance.yaml
vendored
@@ -46,13 +46,17 @@ 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
|
||||
title: '[bot] Update Python packages'
|
||||
commit-message: Update Python packages and pre-commit hooks
|
||||
title: '[bot] Update Python packages and pre-commit hooks'
|
||||
branch: auto-package-updates
|
||||
base: master
|
||||
delete-branch: true
|
||||
|
||||
115
.github/workflows/selfdrive_tests.yaml
vendored
115
.github/workflows/selfdrive_tests.yaml
vendored
@@ -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 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
|
||||
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
|
||||
|
||||
PYTEST: pytest --continue-on-collection-errors --cov --cov-report=xml --cov-append --durations=0 --durations-min=5 --hypothesis-seed 0 -n logical
|
||||
|
||||
@@ -45,6 +45,7 @@ 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'
|
||||
@@ -61,22 +62,20 @@ jobs:
|
||||
cd $STRIPPED_DIR
|
||||
${{ env.RUN }} "release/check-dirty.sh && \
|
||||
MAX_EXAMPLES=5 $PYTEST -m 'not slow' selfdrive/car"
|
||||
- name: static analysis
|
||||
timeout-minutes: 1
|
||||
- name: pre-commit
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
cd $GITHUB_WORKSPACE
|
||||
cp .pre-commit-config.yaml $STRIPPED_DIR
|
||||
cp pyproject.toml $STRIPPED_DIR
|
||||
cd $STRIPPED_DIR
|
||||
${{ env.RUN }} "scripts/lint.sh"
|
||||
${{ 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"
|
||||
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
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' }}
|
||||
arch: ${{ fromJson('["x86_64"]') }} # TODO: Re-add build test for aarch64 once we switched to ubuntu-2404
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -85,7 +84,7 @@ jobs:
|
||||
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot'
|
||||
run: |
|
||||
echo "PUSH_IMAGE=true" >> "$GITHUB_ENV"
|
||||
echo "TARGET_ARCHITECTURE=${{ matrix.arch }}" >> "$GITHUB_ENV"
|
||||
: # (TODO: Re-add this once we test other archs) echo "TARGET_ARCHITECTURE=${{ matrix.arch }}" >> "$GITHUB_ENV"
|
||||
$DOCKER_LOGIN
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
with:
|
||||
@@ -94,7 +93,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
|
||||
@@ -104,36 +103,11 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: ./tools/mac_setup.sh
|
||||
env:
|
||||
SKIP_PROMPT: 1
|
||||
# package install has DeprecationWarnings
|
||||
PYTHONWARNINGS: default
|
||||
- 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
|
||||
- name: Test openpilot environment
|
||||
run: . .venv/bin/activate && scons -h
|
||||
|
||||
static_analysis:
|
||||
name: static analysis
|
||||
@@ -144,12 +118,13 @@ 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: static analysis
|
||||
timeout-minutes: 1
|
||||
run: ${{ env.RUN }} "scripts/lint.sh"
|
||||
- name: pre-commit
|
||||
timeout-minutes: 4
|
||||
run: ${{ env.RUN }} "unset PYTHONWARNINGS && pre-commit run --all && chmod -R 777 /tmp/pre-commit"
|
||||
|
||||
unit_tests:
|
||||
name: unit tests
|
||||
@@ -335,10 +310,8 @@ 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:
|
||||
@@ -355,5 +328,55 @@ jobs:
|
||||
- name: Upload Test Report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: report-${{ github.event.number }}
|
||||
path: selfdrive/ui/tests/test_ui/report_1/screenshots
|
||||
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 }}
|
||||
|
||||
12
.github/workflows/setup-pre-commit/action.yaml
vendored
Normal file
12
.github/workflows/setup-pre-commit/action.yaml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
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' }}
|
||||
4
.github/workflows/stale.yaml
vendored
4
.github/workflows/stale.yaml
vendored
@@ -5,8 +5,8 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
DAYS_BEFORE_PR_CLOSE: 2
|
||||
DAYS_BEFORE_PR_STALE: 9
|
||||
DAYS_BEFORE_PR_CLOSE: 3
|
||||
DAYS_BEFORE_PR_STALE: 14
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
|
||||
8
.github/workflows/tools_tests.yaml
vendored
8
.github/workflows/tools_tests.yaml
vendored
@@ -21,7 +21,7 @@ env:
|
||||
|
||||
BUILD: selfdrive/test/docker_build.sh base
|
||||
|
||||
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
|
||||
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:
|
||||
@@ -74,6 +74,12 @@ 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
.github/workflows/ui_preview.yaml
vendored
91
.github/workflows/ui_preview.yaml
vendored
@@ -1,91 +0,0 @@
|
||||
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 }}
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -14,8 +14,6 @@ model2.png
|
||||
a.out
|
||||
.hypothesis
|
||||
|
||||
/docs_site/
|
||||
|
||||
*.dylib
|
||||
*.DSYM
|
||||
*.d
|
||||
@@ -105,4 +103,4 @@ Pipfile
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
.ionide
|
||||
.ionide
|
||||
@@ -90,6 +90,10 @@ build:
|
||||
- ls -la ${BUILD_DIR}
|
||||
- "echo Building Rest..."
|
||||
- ./release/release_files.py | sort | uniq | rsync -vrRl --files-from=- . $BUILD_DIR/
|
||||
- cp .lfsconfig-prebuilts $BUILD_DIR/.lfsconfig
|
||||
- cp .gitattributes $BUILD_DIR/.gitattributes
|
||||
- echo "selfdrive/**/* filter=lfs diff=lfs merge=lfs -text" >> $BUILD_DIR/.gitattributes
|
||||
- echo "selfdrive/**/*.py -filter -diff -merge" >> $BUILD_DIR/.gitattributes
|
||||
# - cp -pR --parents $(cat release/files_common release/files_tici | sort | uniq) $BUILD_DIR/ 2> >(grep -v 'warning:' >&2)
|
||||
- cd $BUILD_DIR
|
||||
- sed -i '/from .board.jungle import PandaJungle, PandaJungleDFU/s/^/#/' panda/__init__.py # comment panda jungle when prebuilt
|
||||
@@ -159,7 +163,7 @@ build:
|
||||
artifacts: true
|
||||
before_script:
|
||||
- 'apk update && apk upgrade'
|
||||
- 'apk add git bash openssh'
|
||||
- 'apk add git bash openssh git-lfs'
|
||||
- 'eval $(ssh-agent -s)'
|
||||
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
|
||||
- 'mkdir -p ~/.ssh/'
|
||||
|
||||
11
.gitmodules
vendored
11
.gitmodules
vendored
@@ -2,17 +2,20 @@
|
||||
path = panda
|
||||
url = https://github.com/sunnyhaibin/panda.git
|
||||
[submodule "opendbc"]
|
||||
path = opendbc_repo
|
||||
url = https://github.com/sunnypilot/opendbc.git
|
||||
path = opendbc
|
||||
url = https://github.com/sunnyhaibin/opendbc.git
|
||||
[submodule "msgq"]
|
||||
path = msgq_repo
|
||||
url = https://github.com/sunnypilot/msgq.git
|
||||
url = https://github.com/commaai/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/tinygrad/tinygrad.git
|
||||
url = https://github.com/geohot/tinygrad.git
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
[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
|
||||
4
.lfsconfig-prebuilts
Normal file
4
.lfsconfig-prebuilts
Normal file
@@ -0,0 +1,4 @@
|
||||
[lfs]
|
||||
url = https://gitlab.com/sunnypilot/public/sunnypilot-prebuilt-lfs.git/info/lfs
|
||||
pushurl = ssh://git@gitlab.com/sunnypilot/public/sunnypilot-prebuilt-lfs.git
|
||||
locksverify = false
|
||||
98
.pre-commit-config.yaml
Normal file
98
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,98 @@
|
||||
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,25 +5,15 @@ sunnypilot - 0.9.8.0 (2024-xx-xx)
|
||||
* UPDATED: Synced with commaai's openpilot
|
||||
* master commit 4ef757c (July 06, 2024)
|
||||
* NEW❗: Default Driving Model: Notre Dame (July 01, 2024)
|
||||
* NEW❗: Longitudinal: Acceleration Personality thanks to kegman, rav4kumar, and arne1282! (CTV 2.0: GlideTech)
|
||||
* NEW❗: Longitudinal: Acceleration Personality thanks to kegman, rav4kumar, and arne1282!
|
||||
* Select from three distinct acceleration personalities: Eco, Normal, and Sport
|
||||
* Acceleration personalities are integrated directly into the model's acceleration matrix and can be activated in real-time!
|
||||
* NEW❗: Toyota - Drive Mode Selector
|
||||
* When enabled you can control acceleration personality just with press of button!
|
||||
* UPDATED: Dynamic Experimental Control
|
||||
* Switched to weighted moving averages to enhance responsiveness to recent data.
|
||||
* Goal is to improve real-time detection accuracy in dynamic conditions.
|
||||
* Capable of handling the increased complexity that comes with this approach.
|
||||
* Particularly beneficial in environments where recent changes are critical to performance.
|
||||
* NEW❗: Longitudinal: Dynamic Personality thanks to rav4kumar!
|
||||
* Dynamically adjusts following distance and reaction based on your "Driving Personality" setting
|
||||
* Personalities adapt in real-time to your speed and the distance to the lead car
|
||||
* Provides a more responsive and tailored driving experience compared to predefined settings
|
||||
* UPDATED: Driving Personality: Updated mode names
|
||||
* Aggressive, Moderate, Standard, Relaxed
|
||||
* NEW❗: Hyundai CAN: Enable Cruise Main by Default
|
||||
* Set CRUISE MAIN to ON by default when the car starts, without engaging MADS
|
||||
* This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under the "Toggles" menu
|
||||
* NEW❗: Toyota - Enhanced Blind Spot Monitor (BSM) thanks to arne182, rav4kumar, and eFiniLan!
|
||||
* Enables Blind Spot Monitor (BSM) signals parsing in sunnypilot using the factory Blind Spot Monitor (BSM)
|
||||
* sunnypilot will use debugging CAN messages to receive unfiltered BSM signals, allowing detection of more objects
|
||||
@@ -33,14 +23,11 @@ sunnypilot - 0.9.8.0 (2024-xx-xx)
|
||||
* Toyota TSS1/1.5, equipped with factory Blind Spot Monitoring (BSM)
|
||||
* Prius TSS2, equipped with factory Blind Spot Monitoring (BSM)
|
||||
* NOTE: Only enable this feature if your Toyota/Lexus vehicle has factory Blind Spot Monitor equipped, and mentioned in the supported platforms list
|
||||
* UPDATED: Toyota: TSS2 longitudinal: Custom Tuning (CTV 2.0: GlideTech)
|
||||
* Re-tuned and tested by the community (September 29, 2024)
|
||||
* UPDATED: Toyota: TSS2 longitudinal: Custom Tuning
|
||||
* Re-tuned and tested by the community (July 1, 2024)
|
||||
* UPDATED: Driving Model Selector v5
|
||||
* NEW❗: Driving Model additions
|
||||
* Notre Dame (July 01, 2024) - NDv3
|
||||
* UPDATED: Neural Network Lateral Control (NNLC)
|
||||
* NEW❗: Remove Lateral Jerk Response (Alpha)
|
||||
* FIXED: Hotfix for "lazy" steering performance in tighter curves thanks to twilsonco!
|
||||
* UPDATED: Toyota: Continued support for Smart DSU (SDSU) and Radar CAN Filter
|
||||
* 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
|
||||
@@ -50,18 +37,11 @@ sunnypilot - 0.9.8.0 (2024-xx-xx)
|
||||
* 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
|
||||
* FIXED: Experimental Model Distance Button Hold
|
||||
* Experimental Model toggle with distance button hold no longer changes Personality
|
||||
* Personality setting remains consistent when switching between Chill and Experimental Mode
|
||||
* 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
|
||||
* Ford F-150 2022-23 support
|
||||
* Ford F-150 Lightning 2021-23 support
|
||||
* Ford Mustang Mach-E 2021-23 support
|
||||
* Hyundai Kona Electric Non-SCC 2019 support thanks to NikitaNekrasov!
|
||||
* Kia Ceed Plug-in Hybrid Non-SCC 2022 support thanks to TerminatorNL!
|
||||
|
||||
sunnypilot - 0.9.7.1 (2024-06-13)
|
||||
@@ -99,8 +79,6 @@ sunnypilot - 0.9.7.1 (2024-06-13)
|
||||
* Force sunnypilot in the offroad state even when the car is on
|
||||
* When Forced Offroad mode is on, allows changing offroad-only settings even when the car is turned on
|
||||
* To engage/disengage Force Offroad, go to Settings -> Device panel
|
||||
* NEW❗: Ford CAN-FD longitudinal
|
||||
* NEW❗: Parse speed limit sign recognition from camera for certain supported platforms
|
||||
* UPDATED: Auto Lane Change Timer -> Auto Lane Change by Blinker
|
||||
* NEW❗: New "Off" option to disable lane change by blinker
|
||||
* UPDATED: Pause Lateral Below Speed with Blinker
|
||||
@@ -108,8 +86,6 @@ sunnypilot - 0.9.7.1 (2024-06-13)
|
||||
* Pause lateral actuation with blinker when traveling below the desired speed selected. Default is 20 MPH or 32 km/h.
|
||||
* UPDATED: Hyundai CAN Longitudinal
|
||||
* Auto-enable radar tracks on platforms with applicable Mando radar
|
||||
* UPDATED: Hyundai CAN-FD Radar-based SCC
|
||||
* Longitudinal support for CAN-FD Radar-based SCC cars
|
||||
* UPDATED: Hyundai CAN-FD Camera-based SCC
|
||||
* NEW❗: Parse lead info for camera-based SCC platforms with longitudinal support
|
||||
* Improve lead tracking when using openpilot longitudinal
|
||||
|
||||
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@@ -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: 35, unit: 'MINUTES') {
|
||||
timeout(time: 20, unit: 'MINUTES') {
|
||||
retry (3) {
|
||||
device(device_ip, "git checkout", extra + "\n" + readFile("selfdrive/test/setup_device_ci.sh"))
|
||||
}
|
||||
|
||||
35
README.md
35
README.md
@@ -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.
|
||||
@@ -223,7 +194,7 @@ The goal of Modified Assistive Driving Safety (MADS) is to enhance the user driv
|
||||
* `SET-` button enables ACC/SCC
|
||||
* `CANCEL` button only disables ACC/SCC
|
||||
* `CRUISE (MAIN)` must be `ON` to use ACC/SCC
|
||||
* `CRUISE (MAIN)` button disables ACC/SCC completely when `OFF` **(strictly enforced in panda safety code)**
|
||||
* `CRUISE (MAIN)` button disables sunnypilot completely when `OFF` **(strictly enforced in panda safety code)**
|
||||
|
||||
### Disengage Lateral ALC on Brake Press Mode toggle
|
||||
Dedicated toggle to handle Lateral state on brake pedal press and release:
|
||||
@@ -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>
|
||||
|
||||
|
||||
11
SConstruct
11
SConstruct
@@ -110,6 +110,7 @@ if arch == "larch64":
|
||||
|
||||
libpath = [
|
||||
"/usr/local/lib",
|
||||
"/usr/lib",
|
||||
"/system/vendor/lib64",
|
||||
f"#third_party/acados/{arch}/lib",
|
||||
]
|
||||
@@ -177,6 +178,7 @@ 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'):
|
||||
@@ -216,6 +218,7 @@ env = Environment(
|
||||
"#third_party/json11",
|
||||
"#third_party/linux/include",
|
||||
"#third_party/snpe/include",
|
||||
"#third_party/qrcode",
|
||||
"#third_party",
|
||||
"#cereal",
|
||||
"#msgq",
|
||||
@@ -243,7 +246,7 @@ env = Environment(
|
||||
COMPILATIONDB_USE_ABSPATH=True,
|
||||
REDNOSE_ROOT="#",
|
||||
tools=["default", "cython", "compilation_db", "rednose_filter"],
|
||||
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
|
||||
toolpath=["#rednose_repo/site_scons/site_tools"],
|
||||
)
|
||||
|
||||
if arch == "Darwin":
|
||||
@@ -283,8 +286,7 @@ if arch == "Darwin":
|
||||
else:
|
||||
envCython["LINKFLAGS"] = ["-pthread", "-shared"]
|
||||
|
||||
np_version = SCons.Script.Value(np.__version__)
|
||||
Export('envCython', 'np_version')
|
||||
Export('envCython')
|
||||
|
||||
# Qt build environment
|
||||
qt_env = env.Clone()
|
||||
@@ -328,7 +330,7 @@ try:
|
||||
except SCons.Errors.UserError:
|
||||
qt_env.Tool('qt')
|
||||
|
||||
qt_env['CPPPATH'] += qt_dirs + ["#third_party/qrcode"]
|
||||
qt_env['CPPPATH'] += qt_dirs# + ["#selfdrive/ui/qt/"]
|
||||
qt_flags = [
|
||||
"-D_REENTRANT",
|
||||
"-DQT_NO_DEBUG",
|
||||
@@ -377,6 +379,7 @@ Export('messaging')
|
||||
|
||||
# Build other submodules
|
||||
SConscript([
|
||||
'body/board/SConscript',
|
||||
'opendbc/can/SConscript',
|
||||
'panda/SConscript',
|
||||
])
|
||||
|
||||
1
body
Submodule
1
body
Submodule
Submodule body added at 0e74db67ae
@@ -137,7 +137,6 @@ struct CarEvent @0x9b1657f34caf3ad3 {
|
||||
speedLimitPreActive @139;
|
||||
speedLimitConfirmed @140;
|
||||
torqueNNLoad @141;
|
||||
hyundaiRadarTracksAvailable @142;
|
||||
|
||||
radarCanErrorDEPRECATED @15;
|
||||
communityFeatureDisallowedDEPRECATED @62;
|
||||
@@ -251,7 +250,7 @@ struct CarState {
|
||||
struct CustomStockLong {
|
||||
cruiseButton @0 :Int16;
|
||||
finalSpeedKph @1 :Float32;
|
||||
vCruiseKphPrevDEPRECATED @2 :Float32;
|
||||
vCruiseKphPrev @2 :Float32;
|
||||
targetSpeed @3 :Float32;
|
||||
vSetDis @4 :Float32;
|
||||
speedDiff @5 :Float32;
|
||||
|
||||
@@ -16,7 +16,6 @@ enum LongitudinalPersonalitySP {
|
||||
moderate @1;
|
||||
standard @2;
|
||||
relaxed @3;
|
||||
overtake @4;
|
||||
}
|
||||
|
||||
enum AccelerationPersonality {
|
||||
@@ -35,17 +34,11 @@ enum ModelGeneration {
|
||||
five @5;
|
||||
}
|
||||
|
||||
enum MpcSource {
|
||||
acc @0;
|
||||
blended @1;
|
||||
}
|
||||
|
||||
struct ControlsStateSP @0x81c2f05a394cf4af {
|
||||
lateralState @0 :Text;
|
||||
personality @8 :LongitudinalPersonalitySP;
|
||||
dynamicPersonality @9 :Bool;
|
||||
accelPersonality @10 :AccelerationPersonality;
|
||||
overtakingAccelerationAssist @11 :Bool;
|
||||
|
||||
lateralControlState :union {
|
||||
indiState @1 :LateralINDIState;
|
||||
@@ -97,10 +90,8 @@ struct LongitudinalPlanSP @0xaedffd8f31e7b55d {
|
||||
desiredTF @13 :Float32;
|
||||
notSpeedLimit @14 :Int16;
|
||||
e2eX @15 :List(Float32);
|
||||
e2eBlendedDEPRECATED @18 :Text;
|
||||
e2eBlended @18 :Text;
|
||||
e2eStatus @22 :Bool;
|
||||
mpcSource @23 :MpcSource;
|
||||
dynamicExperimentalControl @24 :Bool;
|
||||
|
||||
distToTurn @7 :Float32;
|
||||
turnSpeed @8 :Float32;
|
||||
|
||||
@@ -137,6 +137,8 @@ struct FrameData {
|
||||
requestId @28 :UInt32;
|
||||
encodeId @1 :UInt32;
|
||||
|
||||
frameType @7 :FrameType;
|
||||
|
||||
# Timestamps
|
||||
timestampEof @2 :UInt64;
|
||||
timestampSof @8 :UInt64;
|
||||
@@ -156,7 +158,7 @@ struct FrameData {
|
||||
|
||||
temperaturesC @24 :List(Float32);
|
||||
|
||||
enum FrameTypeDEPRECATED {
|
||||
enum FrameType {
|
||||
unknown @0;
|
||||
neo @1;
|
||||
chffrAndroid @2;
|
||||
@@ -173,7 +175,6 @@ struct FrameData {
|
||||
|
||||
frameLengthDEPRECATED @3 :Int32;
|
||||
globalGainDEPRECATED @5 :Int32;
|
||||
frameTypeDEPRECATED @7 :FrameTypeDEPRECATED;
|
||||
androidCaptureResultDEPRECATED @9 :AndroidCaptureResult;
|
||||
lensPosDEPRECATED @11 :Int32;
|
||||
lensSagDEPRECATED @12 :Float32;
|
||||
@@ -336,9 +337,9 @@ enum LaneChangeDirection {
|
||||
|
||||
struct CanData {
|
||||
address @0 :UInt32;
|
||||
busTime @1 :UInt16;
|
||||
dat @2 :Data;
|
||||
src @3 :UInt8;
|
||||
busTimeDEPRECATED @1 :UInt16;
|
||||
}
|
||||
|
||||
struct DeviceState @0xa4d8b5af2aa492eb {
|
||||
@@ -1251,38 +1252,6 @@ 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;
|
||||
@@ -2324,7 +2293,6 @@ struct Event {
|
||||
carParams @69: Car.CarParams;
|
||||
driverMonitoringState @71: DriverMonitoringState;
|
||||
liveLocationKalman @72 :LiveLocationKalman;
|
||||
livePose @129 :LivePose;
|
||||
modelV2 @75 :ModelDataV2;
|
||||
drivingModelData @128 :DrivingModelData;
|
||||
driverStateV2 @92 :DriverStateV2;
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
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
|
||||
import msgq
|
||||
from msgq import fake_event_handle, pub_sock, sub_sock, drain_sock_raw, context
|
||||
|
||||
import os
|
||||
import capnp
|
||||
@@ -18,12 +17,8 @@ from cereal.services import SERVICE_LIST
|
||||
NO_TRAVERSAL_LIMIT = 2**64-1
|
||||
|
||||
|
||||
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:
|
||||
def log_from_bytes(dat: bytes) -> capnp.lib.capnp._DynamicStructReader:
|
||||
with log.Event.from_bytes(dat, traversal_limit_in_words=NO_TRAVERSAL_LIMIT) as msg:
|
||||
return msg
|
||||
|
||||
|
||||
|
||||
52
cereal/messaging/tests/test_messaging.py
Normal file → Executable file
52
cereal/messaging/tests/test_messaging.py
Normal file → Executable file
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import capnp
|
||||
import multiprocessing
|
||||
@@ -5,8 +6,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
|
||||
@@ -27,6 +28,12 @@ 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():
|
||||
@@ -51,12 +58,12 @@ def delayed_send(delay, sock, dat):
|
||||
threading.Timer(delay, send_func).start()
|
||||
|
||||
|
||||
class TestMessaging:
|
||||
class TestMessaging(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# TODO: ZMQ tests are too slow; all sleeps will need to be
|
||||
# replaced with logic to block on the necessary condition
|
||||
if "ZMQ" in os.environ:
|
||||
pytest.skip()
|
||||
raise unittest.SkipTest
|
||||
|
||||
# ZMQ pub socket takes too long to die
|
||||
# sleep to prevent multiple publishers error between tests
|
||||
@@ -68,9 +75,9 @@ class TestMessaging:
|
||||
msg = messaging.new_message(evt)
|
||||
except capnp.lib.capnp.KjException:
|
||||
msg = messaging.new_message(evt, random.randrange(200))
|
||||
assert (time.monotonic() - msg.logMonoTime) < 0.1
|
||||
assert not msg.valid
|
||||
assert evt == msg.which()
|
||||
self.assertLess(time.monotonic() - msg.logMonoTime, 0.1)
|
||||
self.assertFalse(msg.valid)
|
||||
self.assertEqual(evt, msg.which())
|
||||
|
||||
@parameterized.expand(events)
|
||||
def test_pub_sock(self, evt):
|
||||
@@ -92,8 +99,8 @@ class TestMessaging:
|
||||
|
||||
# no wait and no msgs in queue
|
||||
msgs = func(sub_sock)
|
||||
assert isinstance(msgs, list)
|
||||
assert len(msgs) == 0
|
||||
self.assertIsInstance(msgs, list)
|
||||
self.assertEqual(len(msgs), 0)
|
||||
|
||||
# no wait but msgs are queued up
|
||||
num_msgs = random.randrange(3, 10)
|
||||
@@ -101,9 +108,9 @@ class TestMessaging:
|
||||
pub_sock.send(messaging.new_message(sock).to_bytes())
|
||||
time.sleep(0.1)
|
||||
msgs = func(sub_sock)
|
||||
assert isinstance(msgs, list)
|
||||
assert all(isinstance(msg, expected_type) for msg in msgs)
|
||||
assert len(msgs) == num_msgs
|
||||
self.assertIsInstance(msgs, list)
|
||||
self.assertTrue(all(isinstance(msg, expected_type) for msg in msgs))
|
||||
self.assertEqual(len(msgs), num_msgs)
|
||||
|
||||
def test_recv_sock(self):
|
||||
sock = "carState"
|
||||
@@ -113,14 +120,14 @@ class TestMessaging:
|
||||
|
||||
# no wait and no msg in queue, socket should timeout
|
||||
recvd = messaging.recv_sock(sub_sock)
|
||||
assert recvd is None
|
||||
self.assertTrue(recvd is None)
|
||||
|
||||
# no wait and one msg in queue
|
||||
msg = random_carstate()
|
||||
pub_sock.send(msg.to_bytes())
|
||||
time.sleep(0.01)
|
||||
recvd = messaging.recv_sock(sub_sock)
|
||||
assert isinstance(recvd, capnp._DynamicStructReader)
|
||||
self.assertIsInstance(recvd, capnp._DynamicStructReader)
|
||||
# https://github.com/python/mypy/issues/13038
|
||||
assert_carstate(msg.carState, recvd.carState)
|
||||
|
||||
@@ -132,16 +139,16 @@ class TestMessaging:
|
||||
|
||||
# no msg in queue, socket should timeout
|
||||
recvd = messaging.recv_one(sub_sock)
|
||||
assert recvd is None
|
||||
self.assertTrue(recvd is None)
|
||||
|
||||
# one msg in queue
|
||||
msg = random_carstate()
|
||||
pub_sock.send(msg.to_bytes())
|
||||
recvd = messaging.recv_one(sub_sock)
|
||||
assert isinstance(recvd, capnp._DynamicStructReader)
|
||||
self.assertIsInstance(recvd, capnp._DynamicStructReader)
|
||||
assert_carstate(msg.carState, recvd.carState)
|
||||
|
||||
@pytest.mark.xfail(condition="ZMQ" in os.environ, reason='ZMQ detected')
|
||||
@zmq_expected_failure
|
||||
def test_recv_one_or_none(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
@@ -150,13 +157,13 @@ class TestMessaging:
|
||||
|
||||
# no msg in queue, socket shouldn't block
|
||||
recvd = messaging.recv_one_or_none(sub_sock)
|
||||
assert recvd is None
|
||||
self.assertTrue(recvd is None)
|
||||
|
||||
# one msg in queue
|
||||
msg = random_carstate()
|
||||
pub_sock.send(msg.to_bytes())
|
||||
recvd = messaging.recv_one_or_none(sub_sock)
|
||||
assert isinstance(recvd, capnp._DynamicStructReader)
|
||||
self.assertIsInstance(recvd, capnp._DynamicStructReader)
|
||||
assert_carstate(msg.carState, recvd.carState)
|
||||
|
||||
def test_recv_one_retry(self):
|
||||
@@ -172,7 +179,7 @@ class TestMessaging:
|
||||
p = multiprocessing.Process(target=messaging.recv_one_retry, args=(sub_sock,))
|
||||
p.start()
|
||||
time.sleep(sock_timeout*15)
|
||||
assert p.is_alive()
|
||||
self.assertTrue(p.is_alive())
|
||||
p.terminate()
|
||||
|
||||
# wait 15 socket timeouts before sending
|
||||
@@ -180,6 +187,9 @@ class TestMessaging:
|
||||
delayed_send(sock_timeout*15, pub_sock, msg.to_bytes())
|
||||
start_time = time.monotonic()
|
||||
recvd = messaging.recv_one_retry(sub_sock)
|
||||
assert (time.monotonic() - start_time) >= sock_timeout*15
|
||||
assert isinstance(recvd, capnp._DynamicStructReader)
|
||||
self.assertGreaterEqual(time.monotonic() - start_time, sock_timeout*15)
|
||||
self.assertIsInstance(recvd, capnp._DynamicStructReader)
|
||||
assert_carstate(msg.carState, recvd.carState)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
44
cereal/messaging/tests/test_pub_sub_master.py
Normal file → Executable file
44
cereal/messaging/tests/test_pub_sub_master.py
Normal file → Executable file
@@ -1,6 +1,8 @@
|
||||
#!/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, \
|
||||
@@ -8,9 +10,9 @@ from cereal.messaging.tests.test_messaging import events, random_sock, random_so
|
||||
zmq_sleep
|
||||
|
||||
|
||||
class TestSubMaster:
|
||||
class TestSubMaster(unittest.TestCase):
|
||||
|
||||
def setup_method(self):
|
||||
def setUp(self):
|
||||
# ZMQ pub socket takes too long to die
|
||||
# sleep to prevent multiple publishers error between tests
|
||||
zmq_sleep(3)
|
||||
@@ -19,21 +21,21 @@ class TestSubMaster:
|
||||
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]:
|
||||
assert len(cast(Sized, p)) == len(events)
|
||||
self.assertEqual(len(cast(Sized, p)), len(events))
|
||||
|
||||
def test_init_state(self):
|
||||
socks = random_socks()
|
||||
sm = messaging.SubMaster(socks)
|
||||
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())
|
||||
self.assertEqual(sm.frame, -1)
|
||||
self.assertFalse(any(sm.updated.values()))
|
||||
self.assertFalse(any(sm.alive.values()))
|
||||
self.assertTrue(all(t == 0. for t in sm.recv_time.values()))
|
||||
self.assertTrue(all(f == 0 for f in sm.recv_frame.values()))
|
||||
self.assertTrue(all(t == 0 for t in sm.logMonoTime.values()))
|
||||
|
||||
for p in [sm.updated, sm.recv_time, sm.recv_frame, sm.alive,
|
||||
sm.sock, sm.data, sm.logMonoTime, sm.valid]:
|
||||
assert len(cast(Sized, p)) == len(socks)
|
||||
self.assertEqual(len(cast(Sized, p)), len(socks))
|
||||
|
||||
def test_getitem(self):
|
||||
sock = "carState"
|
||||
@@ -57,8 +59,8 @@ class TestSubMaster:
|
||||
msg = messaging.new_message(sock)
|
||||
pub_sock.send(msg.to_bytes())
|
||||
sm.update(1000)
|
||||
assert sm.frame == i
|
||||
assert all(sm.updated.values())
|
||||
self.assertEqual(sm.frame, i)
|
||||
self.assertTrue(all(sm.updated.values()))
|
||||
|
||||
def test_update_timeout(self):
|
||||
sock = random_sock()
|
||||
@@ -68,9 +70,9 @@ class TestSubMaster:
|
||||
start_time = time.monotonic()
|
||||
sm.update(timeout)
|
||||
t = time.monotonic() - start_time
|
||||
assert t >= timeout/1000.
|
||||
assert t < 5
|
||||
assert not any(sm.updated.values())
|
||||
self.assertGreaterEqual(t, timeout/1000.)
|
||||
self.assertLess(t, 5)
|
||||
self.assertFalse(any(sm.updated.values()))
|
||||
|
||||
def test_avg_frequency_checks(self):
|
||||
for poll in (True, False):
|
||||
@@ -116,12 +118,12 @@ class TestSubMaster:
|
||||
pub_sock.send(msg.to_bytes())
|
||||
time.sleep(0.01)
|
||||
sm.update(1000)
|
||||
assert sm[sock].vEgo == n
|
||||
self.assertEqual(sm[sock].vEgo, n)
|
||||
|
||||
|
||||
class TestPubMaster:
|
||||
class TestPubMaster(unittest.TestCase):
|
||||
|
||||
def setup_method(self):
|
||||
def setUp(self):
|
||||
# ZMQ pub socket takes too long to die
|
||||
# sleep to prevent multiple publishers error between tests
|
||||
zmq_sleep(3)
|
||||
@@ -154,4 +156,8 @@ class TestPubMaster:
|
||||
if capnp:
|
||||
msg.clear_write_flag()
|
||||
msg = msg.to_bytes()
|
||||
assert msg == recvd, i
|
||||
self.assertEqual(msg, recvd, i)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
13
cereal/messaging/tests/test_services.py
Normal file → Executable file
13
cereal/messaging/tests/test_services.py
Normal file → Executable file
@@ -1,21 +1,26 @@
|
||||
#!/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:
|
||||
class TestServices(unittest.TestCase):
|
||||
|
||||
@parameterized.expand(SERVICE_LIST.keys())
|
||||
def test_services(self, s):
|
||||
service = SERVICE_LIST[s]
|
||||
assert service.frequency <= 104
|
||||
assert service.decimation != 0
|
||||
self.assertTrue(service.frequency <= 104)
|
||||
self.assertTrue(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}")
|
||||
assert ret == 0, "generated services header is not valid C"
|
||||
self.assertEqual(ret, 0, "generated services header is not valid C")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -16,13 +16,13 @@ _services: dict[str, tuple] = {
|
||||
"gyroscope2": (True, 100., 100),
|
||||
"accelerometer": (True, 104., 104),
|
||||
"accelerometer2": (True, 100., 100),
|
||||
"magnetometer": (True, 25.),
|
||||
"magnetometer": (True, 25., 25),
|
||||
"lightSensor": (True, 100., 100),
|
||||
"temperatureSensor": (True, 2., 200),
|
||||
"temperatureSensor2": (True, 2., 200),
|
||||
"gpsNMEA": (True, 9.),
|
||||
"deviceState": (True, 2., 1),
|
||||
"can": (True, 100., 2053), # decimation gives ~3 msgs in a full segment
|
||||
"can": (True, 100., 1223), # decimation gives ~5 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., 10),
|
||||
"longitudinalPlan": (True, 20., 5),
|
||||
"procLog": (True, 0.5, 15),
|
||||
"gpsLocationExternal": (True, 10., 10),
|
||||
"gpsLocation": (True, 1., 1),
|
||||
@@ -47,10 +47,9 @@ _services: dict[str, tuple] = {
|
||||
"gnssMeasurements": (True, 10., 10),
|
||||
"clocks": (True, 0.1, 1),
|
||||
"ubloxRaw": (True, 20.),
|
||||
"livePose": (True, 20., 4),
|
||||
"liveLocationKalman": (True, 20.),
|
||||
"liveLocationKalman": (True, 20., 5),
|
||||
"liveParameters": (True, 20., 5),
|
||||
"cameraOdometry": (True, 20., 10),
|
||||
"cameraOdometry": (True, 20., 5),
|
||||
"lateralPlanDEPRECATED": (True, 20., 5),
|
||||
"thumbnail": (True, 0.2, 1),
|
||||
"onroadEvents": (True, 1., 1),
|
||||
|
||||
@@ -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 = HANDLE_EINTR(fsync(fd));
|
||||
HANDLE_EINTR(close(fd));
|
||||
result = fsync(fd);
|
||||
close(fd);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -232,7 +232,6 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"CustomMapboxTokenSk", PERSISTENT | BACKUP},
|
||||
{"CustomOffsets", PERSISTENT | BACKUP},
|
||||
{"CustomStockLong", PERSISTENT | BACKUP},
|
||||
{"CustomStockLongPlanner", PERSISTENT | BACKUP},
|
||||
{"CustomTorqueLateral", PERSISTENT | BACKUP},
|
||||
{"DevUIInfo", PERSISTENT | BACKUP},
|
||||
{"DisableOnroadUploads", PERSISTENT | BACKUP},
|
||||
@@ -262,15 +261,9 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"HandsOnWheelMonitoring", PERSISTENT | BACKUP},
|
||||
{"HasAcceptedTermsSP", PERSISTENT},
|
||||
{"HideVEgoUi", PERSISTENT | BACKUP},
|
||||
{"HyundaiCruiseMainDefault", PERSISTENT | BACKUP},
|
||||
{"HkgCustomLongTuning", PERSISTENT | BACKUP},
|
||||
{"HkgSmoothStop", PERSISTENT | BACKUP},
|
||||
{"HyundaiCruiseMainDefault", PERSISTENT | BACKUP},
|
||||
{"HotspotOnBoot", PERSISTENT},
|
||||
{"HotspotOnBootConfirmed", PERSISTENT},
|
||||
{"HyundaiRadarTracksAvailable", PERSISTENT},
|
||||
{"HyundaiRadarTracksAvailableCache", PERSISTENT},
|
||||
{"HyundaiRadarTracksAvailablePersistent", PERSISTENT},
|
||||
{"LastCarModel", PERSISTENT | BACKUP},
|
||||
{"LastSpeedLimitSignTap", PERSISTENT},
|
||||
{"LastSunnylinkPingTime", CLEAR_ON_MANAGER_START},
|
||||
@@ -287,7 +280,6 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"NavModelUrl", PERSISTENT | BACKUP},
|
||||
{"NNFF", PERSISTENT | BACKUP},
|
||||
{"NNFFCarModel", PERSISTENT | BACKUP},
|
||||
{"NNFFNoLateralJerk", PERSISTENT | BACKUP},
|
||||
{"OnroadScreenOff", PERSISTENT | BACKUP},
|
||||
{"OnroadScreenOffBrightness", PERSISTENT | BACKUP},
|
||||
{"OnroadScreenOffEvent", PERSISTENT | BACKUP},
|
||||
@@ -298,11 +290,8 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"OsmLocationUrl", PERSISTENT},
|
||||
{"OsmWayTest", PERSISTENT},
|
||||
{"OsmDownloadedDate", PERSISTENT},
|
||||
{"OvertakingAccelerationAssist", PERSISTENT},
|
||||
{"PathOffset", PERSISTENT | BACKUP},
|
||||
{"PauseLateralSpeed", PERSISTENT | BACKUP},
|
||||
{"PCMVCruiseOverride", PERSISTENT | BACKUP},
|
||||
{"PCMVCruiseOverrideSpeed", PERSISTENT | BACKUP},
|
||||
{"QuietDrive", PERSISTENT | BACKUP},
|
||||
{"RoadEdge", PERSISTENT | BACKUP},
|
||||
{"ReverseAccChange", PERSISTENT | BACKUP},
|
||||
@@ -327,12 +316,10 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"TermsVersionSunnypilot", PERSISTENT},
|
||||
{"TorqueDeadzoneDeg", PERSISTENT | BACKUP},
|
||||
{"TorqueFriction", PERSISTENT | BACKUP},
|
||||
{"TorqueLateralJerk", PERSISTENT | BACKUP},
|
||||
{"TorqueMaxLatAccel", PERSISTENT | BACKUP},
|
||||
{"TorquedOverride", PERSISTENT | BACKUP},
|
||||
{"ToyotaAutoLockBySpeed", PERSISTENT | BACKUP},
|
||||
{"ToyotaAutoUnlockByShifter", PERSISTENT | BACKUP},
|
||||
{"ToyotaDriveMode", PERSISTENT | BACKUP},
|
||||
{"ToyotaEnhancedBsm", PERSISTENT | BACKUP},
|
||||
{"ToyotaSnG", PERSISTENT | BACKUP},
|
||||
{"ToyotaTSS2Long", PERSISTENT | BACKUP},
|
||||
|
||||
@@ -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 // 2, 1520 // 2, 567.0 / 4 * 3)
|
||||
_os_fisheye = CameraConfig(2688, 1520, 567.0 / 2 * 3)
|
||||
_ar_ox_config = DeviceCameraConfig(CameraConfig(1928, 1208, 2648.0), _ar_ox_fisheye, _ar_ox_fisheye)
|
||||
_os_config = DeviceCameraConfig(CameraConfig(2688 // 2, 1520 // 2, 1522.0 * 3 / 4), _os_fisheye, _os_fisheye)
|
||||
_os_config = DeviceCameraConfig(CameraConfig(2688, 1520, 2648.0 * 2 / 3), _os_fisheye, _os_fisheye)
|
||||
_neo_config = DeviceCameraConfig(CameraConfig(1164, 874, 910.0), CameraConfig(816, 612, 650.0), _NoneCameraConfig())
|
||||
|
||||
DEVICE_CAMERAS = {
|
||||
|
||||
@@ -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.
|
||||
|
||||
# 287 Supported Cars
|
||||
# 288 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> |Video|
|
||||
|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
@@ -25,7 +25,8 @@ 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|[](##)|[](##)|<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|[](##)|[](##)|<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|[](##)|[](##)|<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-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<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 2017|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<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|[](##)|[](##)|<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 2019-24|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<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|[](##)|[](##)|None||
|
||||
|CUPRA|Ateca 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<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>||
|
||||
|
||||
@@ -1,26 +1,3 @@
|
||||
# openpilot docs
|
||||
# openpilot-docs
|
||||
|
||||
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
|
||||
These docs are autogenerated from [this folder](https://github.com/commaai/openpilot/tree/master/docs) in the main openpilot repository.
|
||||
@@ -29,7 +29,7 @@ pytest
|
||||
cd system/loggerd && pytest .
|
||||
|
||||
# run the linter
|
||||
op lint
|
||||
pre-commit run --all
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
# 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
|
||||
@@ -1,8 +0,0 @@
|
||||
# openpilot glossary
|
||||
|
||||
* **route**:
|
||||
* **segment**: routes are split into one minute chunks called segments.
|
||||
* **panda**: this is . See the repo.
|
||||
* **onroad**:
|
||||
* **offroad**:
|
||||
* **comma 3X**:
|
||||
@@ -1 +0,0 @@
|
||||
../SAFETY.md
|
||||
@@ -1 +0,0 @@
|
||||
# Architecture
|
||||
@@ -1,30 +0,0 @@
|
||||
# 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,14 +0,0 @@
|
||||
# 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.
|
||||
@@ -1,98 +0,0 @@
|
||||
# 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 isn’t defined, but a git grep of COLOR_WHITE shows it’s 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
|
||||
```
|
||||
|
||||

|
||||
|
||||
## 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
|
||||
|
||||

|
||||
@@ -1 +0,0 @@
|
||||
getting-started/what-is-openpilot.md
|
||||
12
docs/new/README.md
Normal file
12
docs/new/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
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/
|
||||
9
docs/new/docs/car-porting/what-is-a-car-port.md
Normal file
9
docs/new/docs/car-porting/what-is-a-car-port.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# 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,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](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).
|
||||
[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).
|
||||
|
||||
|
||||
## How do I use it?
|
||||
4
docs/new/docs/how-to/turning-the-speed-blue.md
Normal file
4
docs/new/docs/how-to/turning-the-speed-blue.md
Normal file
@@ -0,0 +1,4 @@
|
||||
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
docs/new/mkdocs.yml
Normal file
18
docs/new/mkdocs.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
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
mkdocs.yml
38
mkdocs.yml
@@ -1,38 +0,0 @@
|
||||
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 msgq_repo updated: e6c0716e41...da77480a96
1
opendbc
Submodule
1
opendbc
Submodule
Submodule opendbc added at adc1fffe60
Submodule opendbc_repo deleted from 529474a50e
2
panda
2
panda
Submodule panda updated: 55018eafc2...5d92bdc6de
@@ -26,7 +26,7 @@ dependencies = [
|
||||
"pycapnp",
|
||||
"Cython",
|
||||
"setuptools",
|
||||
"numpy",
|
||||
"numpy < 2.0.0", # control does not support numpy 2
|
||||
|
||||
# body / webrtcd
|
||||
"aiohttp",
|
||||
@@ -52,30 +52,27 @@ dependencies = [
|
||||
"websocket_client",
|
||||
|
||||
# acados deps
|
||||
"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'",
|
||||
"casadi",
|
||||
"future-fstrings",
|
||||
|
||||
# these should be removed
|
||||
"psutil",
|
||||
"pycryptodome", # used in updated/casync, panda, body, and a test
|
||||
|
||||
# logreader
|
||||
"zstandard",
|
||||
#logreader
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
docs = [
|
||||
"Jinja2",
|
||||
"natsort",
|
||||
"mkdocs",
|
||||
]
|
||||
|
||||
testing = [
|
||||
"coverage",
|
||||
"hypothesis ==6.47.*",
|
||||
"import-linter",
|
||||
"mypy",
|
||||
"pre-commit",
|
||||
"pytest",
|
||||
"pytest-cov",
|
||||
"pytest-cpp",
|
||||
@@ -86,25 +83,30 @@ testing = [
|
||||
"pytest-asyncio",
|
||||
"pytest-mock",
|
||||
"pytest-repeat",
|
||||
"ruff",
|
||||
"codespell",
|
||||
"ruff"
|
||||
]
|
||||
|
||||
dev = [
|
||||
"av",
|
||||
"azure-identity",
|
||||
"azure-storage-blob",
|
||||
"breathe",
|
||||
"control",
|
||||
"dictdiffer",
|
||||
"flaky",
|
||||
"inputs",
|
||||
"lru-dict",
|
||||
"matplotlib",
|
||||
"metadrive-simulator@git+https://github.com/commaai/metadrive@opencv_headless ; platform_machine != 'aarch64'",
|
||||
"metadrive-simulator; platform_machine != 'aarch64'",
|
||||
"mpld3",
|
||||
"myst-parser",
|
||||
"natsort",
|
||||
"opencv-python-headless",
|
||||
"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",
|
||||
@@ -114,8 +116,12 @@ 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"
|
||||
|
||||
@@ -126,12 +132,9 @@ 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=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=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"
|
||||
cpp_files = "test_*"
|
||||
cpp_harness = "selfdrive/test/cpp_harness.py"
|
||||
python_files = "test_*.py"
|
||||
@@ -164,13 +167,6 @@ 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 = [
|
||||
@@ -227,7 +223,7 @@ lint.ignore = [
|
||||
"UP038", # (x, y) -> x|y for isinstance
|
||||
]
|
||||
line-length = 160
|
||||
target-version ="py311"
|
||||
target-version="py311"
|
||||
exclude = [
|
||||
"body",
|
||||
"cereal",
|
||||
@@ -239,8 +235,7 @@ 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"
|
||||
@@ -252,6 +247,5 @@ lint.flake8-implicit-str-concat.allow-multiline = false
|
||||
|
||||
[tool.coverage.run]
|
||||
concurrency = ["multiprocessing", "thread"]
|
||||
|
||||
[tool.ruff.format]
|
||||
quote-style = "preserve"
|
||||
|
||||
Submodule rednose_repo updated: 023a6195db...72b3479bab
@@ -48,6 +48,7 @@ git remote remove origin || true # ensure cleanup
|
||||
git remote add origin $GIT_ORIGIN
|
||||
#git push origin -d $DEV_BRANCH || true # Ensuring we delete the remote branch if it exists as we are wiping it out
|
||||
git fetch origin $DEV_BRANCH || (git checkout -b $DEV_BRANCH && git commit --allow-empty -m "sunnypilot v$VERSION release" && git push -u origin $DEV_BRANCH)
|
||||
git lfs install
|
||||
|
||||
echo "[-] committing version $VERSION T=$SECONDS"
|
||||
git add -f .
|
||||
|
||||
2
release/ci/sync-lfs.sh
Executable file → Normal file
2
release/ci/sync-lfs.sh
Executable file → Normal 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 --all origin
|
||||
git lfs fetch --all; git lfs push origin main
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
third_party/libyuv/x86_64/**
|
||||
third_party/snpe/x86_64/**
|
||||
third_party/snpe/x86_64-linux-clang/**
|
||||
third_party/acados/x86_64/**
|
||||
@@ -1,15 +0,0 @@
|
||||
third_party/libyuv/larch64/**
|
||||
third_party/snpe/larch64**
|
||||
third_party/snpe/aarch64-ubuntu-gcc7.5/*
|
||||
third_party/acados/larch64/**
|
||||
|
||||
system/camerad/cameras/camera_qcom2.cc
|
||||
system/camerad/cameras/camera_qcom2.h
|
||||
system/camerad/cameras/camera_util.cc
|
||||
system/camerad/cameras/camera_util.h
|
||||
system/camerad/cameras/process_raw.cl
|
||||
|
||||
system/qcomgpsd/*
|
||||
|
||||
selfdrive/ui/qt/spinner_larch64
|
||||
selfdrive/ui/qt/text_larch64
|
||||
@@ -10,12 +10,14 @@ ROOT = HERE + "/.."
|
||||
# - minimizing release download size
|
||||
# - keeping the diff readable
|
||||
blacklist = [
|
||||
"body/STL/",
|
||||
|
||||
"panda/drivers/",
|
||||
"panda/examples/",
|
||||
"panda/tests/safety/",
|
||||
|
||||
"opendbc_repo/dbc/.*.dbc$",
|
||||
"opendbc_repo/dbc/generator/",
|
||||
"opendbc/.*.dbc$",
|
||||
"opendbc/generator/",
|
||||
|
||||
"cereal/.*test.*",
|
||||
"^common/tests/",
|
||||
@@ -26,6 +28,7 @@ blacklist = [
|
||||
"selfdrive/car/tests/test_models.*",
|
||||
|
||||
"^tools/",
|
||||
"^scripts/",
|
||||
"^tinygrad_repo/",
|
||||
|
||||
"matlab.*.md",
|
||||
@@ -115,55 +118,55 @@ whitelist = [
|
||||
"tinygrad_repo/tinygrad/.*.py",
|
||||
|
||||
# TODO: do this automatically
|
||||
"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",
|
||||
"opendbc/comma_body.dbc",
|
||||
"opendbc/chrysler_ram_hd_generated.dbc",
|
||||
"opendbc/chrysler_ram_dt_generated.dbc",
|
||||
"opendbc/chrysler_pacifica_2017_hybrid_generated.dbc",
|
||||
"opendbc/chrysler_pacifica_2017_hybrid_private_fusion.dbc",
|
||||
"opendbc/gm_global_a_powertrain_generated.dbc",
|
||||
"opendbc/gm_global_a_object.dbc",
|
||||
"opendbc/gm_global_a_chassis.dbc",
|
||||
"opendbc/FORD_CADS.dbc",
|
||||
"opendbc/ford_fusion_2018_adas.dbc",
|
||||
"opendbc/ford_lincoln_base_pt.dbc",
|
||||
"opendbc/honda_accord_2018_can_generated.dbc",
|
||||
"opendbc/acura_ilx_2016_can_generated.dbc",
|
||||
"opendbc/acura_rdx_2018_can_generated.dbc",
|
||||
"opendbc/acura_rdx_2020_can_generated.dbc",
|
||||
"opendbc/honda_civic_touring_2016_can_generated.dbc",
|
||||
"opendbc/honda_civic_hatchback_ex_2017_can_generated.dbc",
|
||||
"opendbc/honda_crv_touring_2016_can_generated.dbc",
|
||||
"opendbc/honda_crv_ex_2017_can_generated.dbc",
|
||||
"opendbc/honda_crv_ex_2017_body_generated.dbc",
|
||||
"opendbc/honda_crv_executive_2016_can_generated.dbc",
|
||||
"opendbc/honda_fit_ex_2018_can_generated.dbc",
|
||||
"opendbc/honda_odyssey_exl_2018_generated.dbc",
|
||||
"opendbc/honda_odyssey_extreme_edition_2018_china_can_generated.dbc",
|
||||
"opendbc/honda_insight_ex_2019_can_generated.dbc",
|
||||
"opendbc/acura_ilx_2016_nidec.dbc",
|
||||
"opendbc/honda_civic_ex_2022_can_generated.dbc",
|
||||
"opendbc/hyundai_canfd.dbc",
|
||||
"opendbc/hyundai_kia_generic.dbc",
|
||||
"opendbc/hyundai_kia_mando_front_radar_generated.dbc",
|
||||
"opendbc/mazda_2017.dbc",
|
||||
"opendbc/nissan_x_trail_2017_generated.dbc",
|
||||
"opendbc/nissan_leaf_2018_generated.dbc",
|
||||
"opendbc/subaru_global_2017_generated.dbc",
|
||||
"opendbc/subaru_global_2020_hybrid_generated.dbc",
|
||||
"opendbc/subaru_outback_2015_generated.dbc",
|
||||
"opendbc/subaru_outback_2019_generated.dbc",
|
||||
"opendbc/subaru_forester_2017_generated.dbc",
|
||||
"opendbc/toyota_tnga_k_pt_generated.dbc",
|
||||
"opendbc/toyota_new_mc_pt_generated.dbc",
|
||||
"opendbc/toyota_nodsu_pt_generated.dbc",
|
||||
"opendbc/toyota_adas.dbc",
|
||||
"opendbc/toyota_tss2_adas.dbc",
|
||||
"opendbc/vw_golf_mk4.dbc",
|
||||
"opendbc/vw_mqb_2010.dbc",
|
||||
"opendbc/tesla_can.dbc",
|
||||
"opendbc/tesla_radar_bosch_generated.dbc",
|
||||
"opendbc/tesla_radar_continental_generated.dbc",
|
||||
"opendbc/tesla_powertrain.dbc",
|
||||
]
|
||||
|
||||
# Sunnypilot whitelist
|
||||
|
||||
@@ -1,390 +0,0 @@
|
||||
#!/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/*
|
||||
@@ -1,82 +0,0 @@
|
||||
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
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/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
scripts/pyupgrade.sh
Executable file
7
scripts/pyupgrade.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
pip install --upgrade pyupgrade
|
||||
|
||||
git ls-files '*.py' | grep -v 'third_party/' | xargs pyupgrade --py311-plus
|
||||
@@ -7,12 +7,10 @@ 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.
|
||||
@@ -218,7 +216,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)[1]
|
||||
dat = packer.make_can_msg("GAS_COMMAND", 0, values)[2]
|
||||
|
||||
checksum = crc8_pedal(dat[:-1])
|
||||
values["CHECKSUM_PEDAL"] = checksum
|
||||
@@ -226,39 +224,8 @@ 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, 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)
|
||||
return [addr, 0, dat, bus]
|
||||
|
||||
|
||||
def get_safety_config(safety_model, safety_param = None):
|
||||
|
||||
@@ -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):
|
||||
super().__init__(dbc_name, CP, VM)
|
||||
self.frame = 0
|
||||
self.packer = CANPacker(dbc_name)
|
||||
|
||||
# PIDs
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import math
|
||||
from cereal import car
|
||||
from openpilot.selfdrive.car import DT_CTRL, get_safety_config
|
||||
from openpilot.common.realtime import DT_CTRL
|
||||
from openpilot.selfdrive.car import get_safety_config
|
||||
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
|
||||
from openpilot.selfdrive.car.body.values import SPEED_FROM_RPM
|
||||
|
||||
|
||||
@@ -11,10 +11,9 @@ 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
|
||||
from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper, DT_CTRL
|
||||
|
||||
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
|
||||
|
||||
@@ -4,7 +4,8 @@ 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.selfdrive.car import DT_CTRL, apply_meas_steer_torque_limits
|
||||
from openpilot.common.realtime import DT_CTRL
|
||||
from openpilot.selfdrive.car import 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
|
||||
@@ -15,8 +16,9 @@ ButtonType = car.CarState.ButtonEvent.Type
|
||||
|
||||
class CarController(CarControllerBase):
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
super().__init__(dbc_name, CP, VM)
|
||||
self.CP = CP
|
||||
self.apply_steer_last = 0
|
||||
self.frame = 0
|
||||
|
||||
self.hud_count = 0
|
||||
self.last_lkas_falling_edge = 0
|
||||
@@ -269,8 +271,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 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))
|
||||
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))
|
||||
cruise_button = self.get_button_type(self.button_type)
|
||||
return cruise_button
|
||||
|
||||
|
||||
@@ -4,6 +4,35 @@ 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',
|
||||
@@ -26,7 +55,6 @@ FW_VERSIONS = {
|
||||
],
|
||||
(Ecu.fwdRadar, 0x753, None): [
|
||||
b'04672758AA',
|
||||
b'04672758AB',
|
||||
b'68226356AF',
|
||||
b'68226356AH',
|
||||
b'68226356AI',
|
||||
@@ -48,7 +76,6 @@ FW_VERSIONS = {
|
||||
b'68352654AE ',
|
||||
b'68366851AH ',
|
||||
b'68366853AE ',
|
||||
b'68366853AG ',
|
||||
b'68372861AF ',
|
||||
],
|
||||
(Ecu.transmission, 0x7e1, None): [
|
||||
@@ -62,7 +89,6 @@ FW_VERSIONS = {
|
||||
b'68277374AD',
|
||||
b'68277374AN',
|
||||
b'68367471AC',
|
||||
b'68367471AD',
|
||||
b'68380571AB',
|
||||
],
|
||||
},
|
||||
@@ -155,39 +181,26 @@ 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',
|
||||
@@ -232,7 +245,6 @@ FW_VERSIONS = {
|
||||
b'68416680AE ',
|
||||
b'68416680AF ',
|
||||
b'68416680AG ',
|
||||
b'68444228AC ',
|
||||
b'68444228AD ',
|
||||
b'68444228AE ',
|
||||
b'68444228AF ',
|
||||
@@ -390,7 +402,6 @@ FW_VERSIONS = {
|
||||
b'68294051AI',
|
||||
b'68294052AG',
|
||||
b'68294052AH',
|
||||
b'68294059AI',
|
||||
b'68294063AG',
|
||||
b'68294063AH',
|
||||
b'68294063AI',
|
||||
@@ -401,7 +412,6 @@ FW_VERSIONS = {
|
||||
b'68434858AC',
|
||||
b'68434859AC',
|
||||
b'68434860AC',
|
||||
b'68453471AD',
|
||||
b'68453483AC',
|
||||
b'68453483AD',
|
||||
b'68453487AD',
|
||||
@@ -426,13 +436,11 @@ 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',
|
||||
@@ -523,7 +531,6 @@ FW_VERSIONS = {
|
||||
b'05036066AE ',
|
||||
b'05036193AA ',
|
||||
b'05149368AA ',
|
||||
b'05149374AA ',
|
||||
b'05149591AD ',
|
||||
b'05149591AE ',
|
||||
b'05149592AE ',
|
||||
@@ -554,7 +561,6 @@ FW_VERSIONS = {
|
||||
b'68455145AC ',
|
||||
b'68455145AE ',
|
||||
b'68455146AC ',
|
||||
b'68460927AA ',
|
||||
b'68467915AC ',
|
||||
b'68467916AC ',
|
||||
b'68467936AC ',
|
||||
@@ -573,7 +579,6 @@ FW_VERSIONS = {
|
||||
b'68539650AF',
|
||||
b'68539651AD',
|
||||
b'68586101AA ',
|
||||
b'68586102AA ',
|
||||
b'68586105AB ',
|
||||
b'68629919AC ',
|
||||
b'68629922AC ',
|
||||
@@ -612,8 +617,6 @@ FW_VERSIONS = {
|
||||
b'68520867AE',
|
||||
b'68520867AF',
|
||||
b'68520870AC',
|
||||
b'68520871AC',
|
||||
b'68528325AE',
|
||||
b'68540431AB',
|
||||
b'68540433AB',
|
||||
b'68551676AA',
|
||||
|
||||
@@ -40,8 +40,8 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.flags |= ChryslerFlags.HIGHER_MIN_STEERING_SPEED.value
|
||||
|
||||
# Chrysler
|
||||
if candidate in (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_2017_HYBRID, 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]]
|
||||
@@ -98,9 +98,10 @@ class CarInterface(CarInterfaceBase):
|
||||
*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.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, c.vCruise, self.CS.accEnabled,
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
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
|
||||
@@ -113,16 +114,16 @@ class CarInterface(CarInterfaceBase):
|
||||
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, self.CS.madsEnabled)
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
else:
|
||||
self.CS.madsEnabled = False
|
||||
self.CS.madsEnabled = self.get_sp_started_mads(ret, self.CS.madsEnabled)
|
||||
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 self.CS.button_events):
|
||||
self.get_sp_cancel_cruise_state()
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.get_sp_cancel_cruise_state()
|
||||
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
|
||||
|
||||
if self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed:
|
||||
@@ -135,7 +136,7 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.accEnabled = False
|
||||
self.CS.accEnabled = ret.cruiseState.enabled or self.CS.accEnabled
|
||||
|
||||
ret = self.get_sp_common_state(ret)
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=bool(self.CS.distance_button))
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -145,7 +146,7 @@ class CarInterface(CarInterfaceBase):
|
||||
# events
|
||||
events = self.create_common_events(ret, c, extra_gears=[car.CarState.GearShifter.low], pcm_enable=False)
|
||||
|
||||
events, ret = self.create_sp_events(ret, events)
|
||||
events, ret = self.create_sp_events(self.CS, ret, events)
|
||||
|
||||
# Low speed steer alert hysteresis logic
|
||||
if self.CP.carFingerprint in RAM_DT:
|
||||
@@ -161,7 +162,9 @@ class CarInterface(CarInterfaceBase):
|
||||
if self.low_speed_alert:
|
||||
events.add(car.CarEvent.EventName.belowSteerSpeed)
|
||||
|
||||
ret.customStockLong = self.update_custom_stock_long()
|
||||
ret.customStockLong = self.CS.update_custom_stock_long(self.CC.cruise_button, self.CC.final_speed_kph,
|
||||
self.CC.target_speed, self.CC.v_set_dis,
|
||||
self.CC.speed_diff, self.CC.button_type)
|
||||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ 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
|
||||
|
||||
@@ -40,30 +40,34 @@ class ChryslerCarSpecs(CarSpecs):
|
||||
|
||||
class CAR(Platforms):
|
||||
# Chrysler
|
||||
CHRYSLER_PACIFICA_2018_HYBRID = ChryslerPlatformConfig(
|
||||
[ChryslerCarDocs("Chrysler Pacifica Hybrid 2017-18")],
|
||||
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,
|
||||
)
|
||||
CHRYSLER_PACIFICA_2019_HYBRID = ChryslerPlatformConfig(
|
||||
[ChryslerCarDocs("Chrysler Pacifica Hybrid 2019-24")],
|
||||
CHRYSLER_PACIFICA_2018_HYBRID.specs,
|
||||
CHRYSLER_PACIFICA_2017_HYBRID.specs,
|
||||
)
|
||||
CHRYSLER_PACIFICA_2018 = ChryslerPlatformConfig(
|
||||
[ChryslerCarDocs("Chrysler Pacifica 2017-18")],
|
||||
CHRYSLER_PACIFICA_2018_HYBRID.specs,
|
||||
CHRYSLER_PACIFICA_2017_HYBRID.specs,
|
||||
)
|
||||
CHRYSLER_PACIFICA_2020 = ChryslerPlatformConfig(
|
||||
[
|
||||
ChryslerCarDocs("Chrysler Pacifica 2019-20"),
|
||||
ChryslerCarDocs("Chrysler Pacifica 2021-23", package="All"),
|
||||
],
|
||||
CHRYSLER_PACIFICA_2018_HYBRID.specs,
|
||||
CHRYSLER_PACIFICA_2017_HYBRID.specs,
|
||||
)
|
||||
|
||||
# Dodge
|
||||
DODGE_DURANGO = ChryslerPlatformConfig(
|
||||
[ChryslerCarDocs("Dodge Durango 2020-21")],
|
||||
CHRYSLER_PACIFICA_2018_HYBRID.specs,
|
||||
CHRYSLER_PACIFICA_2017_HYBRID.specs,
|
||||
)
|
||||
|
||||
# Jeep
|
||||
|
||||
@@ -4,13 +4,22 @@ import time
|
||||
|
||||
import cereal.messaging as messaging
|
||||
from panda.python.uds import SERVICE_TYPE
|
||||
from openpilot.selfdrive.car import make_tester_present_msg
|
||||
from openpilot.selfdrive.car import make_can_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 _is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subaddr: int = None) -> bool:
|
||||
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:
|
||||
# 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
|
||||
@@ -24,7 +33,7 @@ def _is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subad
|
||||
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
|
||||
@@ -49,7 +58,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:
|
||||
@@ -85,7 +94,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:")
|
||||
|
||||
@@ -130,8 +130,7 @@ 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_2018_HYBRID,
|
||||
"CHRYSLER_PACIFICA_2017_HYBRID": CHRYSLER.CHRYSLER_PACIFICA_2018_HYBRID,
|
||||
"CHRYSLER PACIFICA HYBRID 2017": CHRYSLER.CHRYSLER_PACIFICA_2017_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,12 +3,12 @@ from opendbc.can.packer import CANPacker
|
||||
from openpilot.common.numpy_fast import clip
|
||||
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, FordFlagsSP
|
||||
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,19 +25,17 @@ def apply_ford_curvature_limits(apply_curvature, apply_curvature_last, current_c
|
||||
|
||||
class CarController(CarControllerBase):
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
super().__init__(dbc_name, CP, VM)
|
||||
self.CP = CP
|
||||
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
|
||||
self.lkas_enabled_last = False
|
||||
self.steer_alert_last = False
|
||||
self.lead_distance_bars_last = None
|
||||
self.path_angle = 0.
|
||||
self.path_offset = 0.
|
||||
self.curvature_rate = 0.
|
||||
|
||||
def update(self, CC, CS, now_nanos):
|
||||
can_sends = []
|
||||
@@ -77,10 +75,7 @@ class CarController(CarControllerBase):
|
||||
# TODO: extended mode
|
||||
mode = 1 if CC.latActive else 0
|
||||
counter = (self.frame // CarControllerParams.STEER_STEP) % 0x10
|
||||
if self.CP.spFlags & FordFlagsSP.SP_ENHANCED_LAT_CONTROL.value:
|
||||
can_sends.append(fordcan.create_lat_ctl2_msg(self.packer, self.CAN, mode, self.path_offset, self.path_angle, -apply_curvature, self.curvature_rate, counter))
|
||||
else:
|
||||
can_sends.append(fordcan.create_lat_ctl2_msg(self.packer, self.CAN, mode, 0., 0., -apply_curvature, 0., counter))
|
||||
can_sends.append(fordcan.create_lat_ctl2_msg(self.packer, self.CAN, mode, 0., 0., -apply_curvature, 0., counter))
|
||||
else:
|
||||
can_sends.append(fordcan.create_lat_ctl_msg(self.packer, self.CAN, CC.latActive, 0., 0., -apply_curvature, 0.))
|
||||
|
||||
@@ -97,7 +92,6 @@ 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 ###
|
||||
|
||||
@@ -24,7 +24,6 @@ class CarState(CarStateBase):
|
||||
|
||||
self.lkas_enabled = None
|
||||
self.prev_lkas_enabled = None
|
||||
self.v_limit = 0
|
||||
|
||||
self.button_states = {button.event_type: False for button in BUTTONS}
|
||||
|
||||
@@ -73,10 +72,6 @@ class CarState(CarStateBase):
|
||||
ret.cruiseState.nonAdaptive = cp.vl["Cluster_Info1_FD1"]["AccEnbl_B_RqDrv"] == 0
|
||||
ret.cruiseState.standstill = cp.vl["EngBrakeData"]["AccStopMde_D_Rq"] == 3
|
||||
ret.accFaulted = cp.vl["EngBrakeData"]["CcStat_D_Actl"] in (1, 2)
|
||||
|
||||
if self.CP.flags & FordFlags.CANFD:
|
||||
ret.cruiseState.speedLimit = self.update_traffic_signals(cp_cam)
|
||||
|
||||
if not self.CP.openpilotLongitudinalControl:
|
||||
ret.accFaulted = ret.accFaulted or cp_cam.vl["ACCDATA"]["CmbbDeny_B_Actl"] == 1
|
||||
|
||||
@@ -134,16 +129,6 @@ class CarState(CarStateBase):
|
||||
|
||||
return ret
|
||||
|
||||
def update_traffic_signals(self, cp_cam):
|
||||
# TODO: Check if CAN platforms have the same signals
|
||||
if self.CP.flags & FordFlags.CANFD:
|
||||
self.v_limit = cp_cam.vl["Traffic_RecognitnData"]["TsrVLim1MsgTxt_D_Rq"]
|
||||
v_limit_unit = cp_cam.vl["Traffic_RecognitnData"]["TsrVlUnitMsgTxt_D_Rq"]
|
||||
|
||||
speed_factor = CV.MPH_TO_MS if v_limit_unit == 2 else CV.KPH_TO_MS if v_limit_unit == 1 else 0
|
||||
|
||||
return self.v_limit * speed_factor if self.v_limit not in (0, 255) else 0
|
||||
|
||||
@staticmethod
|
||||
def get_can_parser(CP):
|
||||
messages = [
|
||||
@@ -200,11 +185,6 @@ class CarState(CarStateBase):
|
||||
("IPMA_Data", 1),
|
||||
]
|
||||
|
||||
if CP.flags & FordFlags.CANFD:
|
||||
messages += [
|
||||
("Traffic_RecognitnData", 1),
|
||||
]
|
||||
|
||||
if CP.enableBsm and CP.flags & FordFlags.CANFD:
|
||||
messages += [
|
||||
("Side_Detect_L_Stat", 5),
|
||||
|
||||
@@ -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)[1]
|
||||
dat = packer.make_can_msg("LateralMotionControl2", 0, values)[2]
|
||||
values["LatCtlPath_No_Cs"] = calculate_lat_ctl2_checksum(mode, counter, dat)
|
||||
|
||||
return packer.make_can_msg("LateralMotionControl2", CAN.main, values)
|
||||
|
||||
@@ -3,8 +3,7 @@ from panda import Panda
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
from openpilot.selfdrive.car import create_button_events, get_safety_config
|
||||
from openpilot.selfdrive.car.ford.fordcan import CanBus
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.selfdrive.car.ford.values import Ecu, FordFlags, FordFlagsSP
|
||||
from openpilot.selfdrive.car.ford.values import Ecu, FordFlags
|
||||
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
@@ -19,15 +18,13 @@ class CarInterface(CarInterfaceBase):
|
||||
@staticmethod
|
||||
def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs):
|
||||
ret.carName = "ford"
|
||||
ret.dashcamOnly = bool(ret.flags & FordFlags.CANFD)
|
||||
|
||||
ret.radarUnavailable = True
|
||||
ret.steerControlType = car.CarParams.SteerControlType.angle
|
||||
ret.steerActuatorDelay = 0.2
|
||||
ret.steerLimitTimer = 1.0
|
||||
|
||||
if Params().get("DongleId", encoding='utf8') in ("4fde83db16dc0802", "112e4d6e0cad05e1", "e36b272d5679115f", "24574459dd7fb3e0", "83a4e056c7072678"):
|
||||
ret.spFlags |= FordFlagsSP.SP_ENHANCED_LAT_CONTROL.value
|
||||
|
||||
CAN = CanBus(fingerprint=fingerprint)
|
||||
cfgs = [get_safety_config(car.CarParams.SafetyModel.ford)]
|
||||
if CAN.main >= 4:
|
||||
@@ -54,13 +51,6 @@ class CarInterface(CarInterfaceBase):
|
||||
if config_tja != 0xFF or config_lca != 0xFF:
|
||||
ret.dashcamOnly = True
|
||||
|
||||
if ret.spFlags & FordFlagsSP.SP_ENHANCED_LAT_CONTROL:
|
||||
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_FORD_ENHANCED_LAT_CONTROL
|
||||
|
||||
ret.longitudinalTuning.kpBP = [0.]
|
||||
ret.longitudinalTuning.kpV = [0.5]
|
||||
ret.longitudinalTuning.kiV = [0.]
|
||||
|
||||
# Auto Transmission: 0x732 ECU or Gear_Shift_by_Wire_FD1
|
||||
found_ecus = [fw.ecu for fw in car_fw]
|
||||
if Ecu.shiftByWire in found_ecus or 0x5A in fingerprint[CAN.main] or docs:
|
||||
@@ -89,9 +79,10 @@ class CarInterface(CarInterfaceBase):
|
||||
*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.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, c.vCruise, self.CS.accEnabled)
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
self.CS.button_events, c.vCruise)
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if self.enable_mads:
|
||||
@@ -99,15 +90,15 @@ class CarInterface(CarInterfaceBase):
|
||||
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, 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 self.CS.button_events):
|
||||
self.get_sp_cancel_cruise_state()
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.get_sp_cancel_cruise_state()
|
||||
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
|
||||
|
||||
if self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed:
|
||||
@@ -115,7 +106,7 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.accEnabled = False
|
||||
self.CS.accEnabled = ret.cruiseState.enabled or self.CS.accEnabled
|
||||
|
||||
ret = self.get_sp_common_state(ret)
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=bool(self.CS.distance_button))
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -124,7 +115,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
events = self.create_common_events(ret, c, extra_gears=[GearShifter.manumatic], pcm_enable=False)
|
||||
|
||||
events, ret = self.create_sp_events(ret, events)
|
||||
events, ret = self.create_sp_events(self.CS, ret, events)
|
||||
|
||||
if not self.CS.vehicle_sensors_valid:
|
||||
events.add(car.CarEvent.EventName.vehicleSensorsInvalid)
|
||||
|
||||
@@ -11,7 +11,6 @@ DELPHI_ESR_RADAR_MSGS = list(range(0x500, 0x540))
|
||||
DELPHI_MRR_RADAR_START_ADDR = 0x120
|
||||
DELPHI_MRR_RADAR_MSG_COUNT = 64
|
||||
|
||||
STEER_ASSIST_DATA_MSGS = 0x3d7
|
||||
|
||||
def _create_delphi_esr_radar_can_parser(CP) -> CANParser:
|
||||
msg_n = len(DELPHI_ESR_RADAR_MSGS)
|
||||
@@ -29,9 +28,6 @@ def _create_delphi_mrr_radar_can_parser(CP) -> CANParser:
|
||||
|
||||
return CANParser(RADAR.DELPHI_MRR, messages, CanBus(CP).radar)
|
||||
|
||||
def _create_steer_assist_data(CP) -> CANParser:
|
||||
messages = [("Steer_Assist_Data", 20)]
|
||||
return CANParser(RADAR.STEER_ASSIST_DATA, messages, CanBus(CP).camera)
|
||||
|
||||
class RadarInterface(RadarInterfaceBase):
|
||||
def __init__(self, CP):
|
||||
@@ -49,10 +45,6 @@ class RadarInterface(RadarInterfaceBase):
|
||||
elif self.radar == RADAR.DELPHI_MRR:
|
||||
self.rcp = _create_delphi_mrr_radar_can_parser(CP)
|
||||
self.trigger_msg = DELPHI_MRR_RADAR_START_ADDR + DELPHI_MRR_RADAR_MSG_COUNT - 1
|
||||
elif self.radar == RADAR.STEER_ASSIST_DATA:
|
||||
self.rcp = _create_steer_assist_data(CP)
|
||||
self.trigger_msg = STEER_ASSIST_DATA_MSGS
|
||||
|
||||
else:
|
||||
raise ValueError(f"Unsupported radar: {self.radar}")
|
||||
|
||||
@@ -76,67 +68,11 @@ class RadarInterface(RadarInterfaceBase):
|
||||
self._update_delphi_esr()
|
||||
elif self.radar == RADAR.DELPHI_MRR:
|
||||
self._update_delphi_mrr()
|
||||
elif self.radar == RADAR.STEER_ASSIST_DATA:
|
||||
self._update_steer_assist_data()
|
||||
|
||||
ret.points = list(self.pts.values())
|
||||
self.updated_messages.clear()
|
||||
return ret
|
||||
|
||||
def _update_steer_assist_data(self):
|
||||
msg = self.rcp.vl["Steer_Assist_Data"]
|
||||
updated_msg = self.updated_messages
|
||||
|
||||
dRel = msg['CmbbObjDistLong_L_Actl']
|
||||
confidence = msg['CmbbObjConfdnc_D_Stat']
|
||||
new_track = False
|
||||
|
||||
# if dRel < 1022:
|
||||
if confidence > 0:
|
||||
if 0 not in self.pts:
|
||||
self.pts[0] = car.RadarData.RadarPoint.new_message()
|
||||
self.pts[0].trackId = self.track_id
|
||||
self.vRelCol[0] = collections.deque(maxlen=20)
|
||||
self.track_id += 1
|
||||
new_track = True
|
||||
|
||||
yRel = msg['CmbbObjDistLat_L_Actl']
|
||||
vRel = msg['CmbbObjRelLong_V_Actl']
|
||||
yvRel = msg['CmbbObjRelLat_V_Actl']
|
||||
calc = 0
|
||||
if not new_track:
|
||||
# if this is a newly created track - we don't have historical data so skip it
|
||||
# if we are on the same track
|
||||
# Let's see if we are moving:
|
||||
# positive gap - lead is moving faster than us
|
||||
# negative gap - lead is moving slower than us
|
||||
dDiff = dRel - self.pts[0].dRel
|
||||
if (abs(vRel) < 1.0e-2):
|
||||
self.vRelCol[0].append(dDiff)
|
||||
vRel = sum(self.vRelCol[0])
|
||||
calc = 1
|
||||
else:
|
||||
if len(self.vRelCol[0]) > 0:
|
||||
self.vRelCol[0].clear()
|
||||
|
||||
if abs(self.pts[0].vRel - vRel) > 2 or abs(self.pts[0].dRel - dRel) > 5:
|
||||
self.pts[0].trackId = self.track_id
|
||||
if len(self.vRelCol[0]) > 0:
|
||||
self.vRelCol[0].clear()
|
||||
self.track_id += 1
|
||||
|
||||
self.pts[0].dRel = dRel # from front of car
|
||||
self.pts[0].yRel = yRel # in car frame's y axis, left is positive
|
||||
self.pts[0].vRel = vRel
|
||||
self.pts[0].aRel = float('nan')
|
||||
self.pts[0].yvRel = yvRel
|
||||
self.pts[0].measured = True
|
||||
else:
|
||||
if 0 in self.pts:
|
||||
del self.pts[0]
|
||||
del self.vRelCol[0]
|
||||
|
||||
|
||||
def _update_delphi_esr(self):
|
||||
for ii in sorted(self.updated_messages):
|
||||
cpt = self.rcp.vl[ii]
|
||||
|
||||
@@ -48,14 +48,9 @@ class FordFlags(IntFlag):
|
||||
CANFD = 1
|
||||
|
||||
|
||||
class FordFlagsSP(IntFlag):
|
||||
SP_ENHANCED_LAT_CONTROL = 1
|
||||
|
||||
|
||||
class RADAR:
|
||||
DELPHI_ESR = 'ford_fusion_2018_adas'
|
||||
DELPHI_MRR = 'FORD_CADS'
|
||||
STEER_ASSIST_DATA = 'ford_lincoln_base_pt'
|
||||
|
||||
|
||||
class Footnote(Enum):
|
||||
@@ -96,7 +91,7 @@ class FordPlatformConfig(PlatformConfig):
|
||||
|
||||
@dataclass
|
||||
class FordCANFDPlatformConfig(FordPlatformConfig):
|
||||
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('ford_lincoln_base_pt', RADAR.STEER_ASSIST_DATA))
|
||||
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('ford_lincoln_base_pt', None))
|
||||
|
||||
def init(self):
|
||||
super().init()
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
from cereal import car
|
||||
import cereal.messaging as messaging
|
||||
from openpilot.common.params import Params
|
||||
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 DT_CTRL, apply_driver_steer_torque_limits
|
||||
from openpilot.selfdrive.car import 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
|
||||
from selfdrive.controls.lib.drive_helpers import GM_V_CRUISE_MIN
|
||||
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
NetworkLocation = car.CarParams.NetworkLocation
|
||||
@@ -22,11 +20,12 @@ MIN_STEER_MSG_INTERVAL_MS = 15
|
||||
|
||||
class CarController(CarControllerBase):
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
super().__init__(dbc_name, CP, VM)
|
||||
self.CP = CP
|
||||
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
|
||||
@@ -40,36 +39,6 @@ class CarController(CarControllerBase):
|
||||
self.packer_obj = CANPacker(DBC[self.CP.carFingerprint]['radar'])
|
||||
self.packer_ch = CANPacker(DBC[self.CP.carFingerprint]['chassis'])
|
||||
|
||||
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
|
||||
self.timer = 0
|
||||
self.final_speed_kph = 0
|
||||
self.init_speed = 0
|
||||
self.current_speed = 0
|
||||
self.v_set_dis = 0
|
||||
self.v_cruise_min = 0
|
||||
self.button_type = 0
|
||||
self.button_select = 0
|
||||
self.button_count = 0
|
||||
self.target_speed = 0
|
||||
self.t_interval = 7
|
||||
self.slc_active_stock = False
|
||||
self.sl_force_active_timer = 0
|
||||
self.v_tsc_state = 0
|
||||
self.slc_state = 0
|
||||
self.m_tsc_state = 0
|
||||
self.cruise_button = None
|
||||
self.speed_diff = 0
|
||||
self.v_tsc = 0
|
||||
self.m_tsc = 0
|
||||
self.steady_speed = 0
|
||||
|
||||
def update(self, CC, CS, now_nanos):
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
@@ -78,40 +47,9 @@ class CarController(CarControllerBase):
|
||||
if hud_v_cruise > 70:
|
||||
hud_v_cruise = 0
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
self.sm.update(0)
|
||||
|
||||
if self.sm.updated['longitudinalPlanSP']:
|
||||
self.v_tsc_state = self.sm['longitudinalPlanSP'].visionTurnControllerState
|
||||
self.slc_state = self.sm['longitudinalPlanSP'].speedLimitControlState
|
||||
self.m_tsc_state = self.sm['longitudinalPlanSP'].turnSpeedControlState
|
||||
self.speed_limit = self.sm['longitudinalPlanSP'].speedLimit
|
||||
self.speed_limit_offset = self.sm['longitudinalPlanSP'].speedLimitOffset
|
||||
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 = GM_V_CRUISE_MIN[self.is_metric] * (CV.KPH_TO_MPH if not self.is_metric else 1)
|
||||
|
||||
# Send CAN commands.
|
||||
can_sends = []
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if not self.last_speed_limit_sign_tap_prev and self.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
|
||||
|
||||
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))
|
||||
slc_active = not sl_inactive and not sl_temp_inactive
|
||||
|
||||
self.slc_active_stock = slc_active
|
||||
|
||||
# Steering (Active: 50Hz, inactive: 10Hz)
|
||||
steer_step = self.params.STEER_STEP if CC.latActive else self.params.INACTIVE_STEER_STEP
|
||||
|
||||
@@ -212,15 +150,6 @@ class CarController(CarControllerBase):
|
||||
self.last_button_frame = self.frame
|
||||
can_sends.append(gmcan.create_buttons(self.packer_pt, CanBus.CAMERA, CS.buttons_counter, CruiseButtons.CANCEL))
|
||||
|
||||
if not (CC.cruiseControl.cancel or CC.cruiseControl.resume) and not self.CP.pcmCruiseSpeed and CS.out.cruiseState.enabled:
|
||||
self.cruise_button = self.get_cruise_buttons(CS, CC.vCruise)
|
||||
if self.cruise_button is not None:
|
||||
send_freq = 1
|
||||
if not (self.v_tsc_state != 0 or self.m_tsc_state > 1) and abs(self.target_speed - self.v_set_dis) <= 2:
|
||||
send_freq = 3
|
||||
if self.frame % 12 < 6: # thanks to mochi86420 for the magic numbers
|
||||
can_sends.extend([gmcan.create_buttons(self.packer_pt, CanBus.CAMERA, (CS.buttons_counter + 2) % 4, self.cruise_button)] * 3)
|
||||
|
||||
if self.CP.networkLocation == NetworkLocation.fwdCamera:
|
||||
# Silence "Take Steering" alert sent by camera, forward PSCMStatus with HandsOffSWlDetectionStatus=1
|
||||
if self.frame % 10 == 0:
|
||||
@@ -234,120 +163,3 @@ class CarController(CarControllerBase):
|
||||
|
||||
self.frame += 1
|
||||
return new_actuators, can_sends
|
||||
|
||||
# multikyd methods, sunnyhaibin logic
|
||||
def get_cruise_buttons_status(self, CS):
|
||||
if not CS.out.cruiseState.enabled or CS.cruise_buttons != CruiseButtons.UNPRESS:
|
||||
self.timer = 40
|
||||
elif self.timer:
|
||||
self.timer -= 1
|
||||
else:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def get_target_speed(self, v_cruise_kph_prev):
|
||||
v_cruise_kph = v_cruise_kph_prev
|
||||
if self.slc_state > 1:
|
||||
v_cruise_kph = (self.speed_limit + self.speed_limit_offset) * CV.MS_TO_KPH
|
||||
if not self.slc_active_stock:
|
||||
v_cruise_kph = v_cruise_kph_prev
|
||||
return v_cruise_kph
|
||||
|
||||
def get_button_type(self, button_type):
|
||||
self.type_status = "type_" + str(button_type)
|
||||
self.button_picker = getattr(self, self.type_status, lambda: "default")
|
||||
return self.button_picker()
|
||||
|
||||
def reset_button(self):
|
||||
if self.button_type != 3:
|
||||
self.button_type = 0
|
||||
|
||||
def type_default(self):
|
||||
self.button_type = 0
|
||||
return None
|
||||
|
||||
def type_0(self):
|
||||
self.button_count = 0
|
||||
self.target_speed = self.init_speed
|
||||
self.speed_diff = self.target_speed - self.v_set_dis
|
||||
if self.target_speed > self.v_set_dis:
|
||||
self.button_type = 1
|
||||
elif self.target_speed < self.v_set_dis and self.v_set_dis > self.v_cruise_min:
|
||||
self.button_type = 2
|
||||
return None
|
||||
|
||||
def type_1(self):
|
||||
cruise_button = CruiseButtons.RES_ACCEL
|
||||
self.button_count += 1
|
||||
if self.target_speed <= self.v_set_dis:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
elif self.button_count > 5:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
return cruise_button
|
||||
|
||||
def type_2(self):
|
||||
cruise_button = CruiseButtons.DECEL_SET
|
||||
self.button_count += 1
|
||||
if self.target_speed >= self.v_set_dis or self.v_set_dis <= self.v_cruise_min:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
elif self.button_count > 5:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
return cruise_button
|
||||
|
||||
def type_3(self):
|
||||
cruise_button = CruiseButtons.UNPRESS
|
||||
self.button_count += 1
|
||||
if self.button_count > self.t_interval:
|
||||
self.button_type = 0
|
||||
return cruise_button
|
||||
|
||||
def get_curve_speed(self, target_speed_kph, v_cruise_kph_prev):
|
||||
if self.v_tsc_state != 0:
|
||||
vision_v_cruise_kph = self.v_tsc * CV.MS_TO_KPH
|
||||
if int(vision_v_cruise_kph) == int(v_cruise_kph_prev):
|
||||
vision_v_cruise_kph = 255
|
||||
else:
|
||||
vision_v_cruise_kph = 255
|
||||
if self.m_tsc_state > 1:
|
||||
map_v_cruise_kph = self.m_tsc * CV.MS_TO_KPH
|
||||
if int(map_v_cruise_kph) == 0.0:
|
||||
map_v_cruise_kph = 255
|
||||
else:
|
||||
map_v_cruise_kph = 255
|
||||
curve_speed = self.curve_speed_hysteresis(min(vision_v_cruise_kph, map_v_cruise_kph) + 2 * CV.MPH_TO_KPH)
|
||||
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))
|
||||
cruise_button = self.get_button_type(self.button_type)
|
||||
return cruise_button
|
||||
|
||||
def curve_speed_hysteresis(self, cur_speed: float, hyst=(0.75 * CV.MPH_TO_KPH)):
|
||||
if cur_speed > self.steady_speed:
|
||||
self.steady_speed = cur_speed
|
||||
elif cur_speed < self.steady_speed - hyst:
|
||||
self.steady_speed = cur_speed
|
||||
return self.steady_speed
|
||||
|
||||
def get_cruise_buttons(self, CS, v_cruise_kph_prev):
|
||||
cruise_button = None
|
||||
if not self.get_cruise_buttons_status(CS):
|
||||
pass
|
||||
elif CS.out.cruiseState.enabled:
|
||||
set_speed_kph = self.get_target_speed(v_cruise_kph_prev)
|
||||
if self.slc_state > 1:
|
||||
target_speed_kph = set_speed_kph
|
||||
else:
|
||||
target_speed_kph = min(v_cruise_kph_prev, set_speed_kph)
|
||||
if self.v_tsc_state != 0 or self.m_tsc_state > 1:
|
||||
self.final_speed_kph = self.get_curve_speed(target_speed_kph, v_cruise_kph_prev)
|
||||
else:
|
||||
self.final_speed_kph = target_speed_kph
|
||||
|
||||
cruise_button = self.get_button_control(CS, self.final_speed_kph, v_cruise_kph_prev) # MPH/KPH based button presses
|
||||
return cruise_button
|
||||
|
||||
@@ -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)[1]
|
||||
dat = packer.make_can_msg("ASCMGasRegenCmd", bus, values)[2]
|
||||
values["GasRegenChecksum"] = (((0xff - dat[1]) & 0xff) << 16) | \
|
||||
(((0xff - dat[2]) & 0xff) << 8) | \
|
||||
((0x100 - dat[3] - idx) & 0xff)
|
||||
|
||||
@@ -6,10 +6,11 @@ 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, get_friction
|
||||
from openpilot.selfdrive.car import create_button_events, get_safety_config
|
||||
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
|
||||
@@ -119,7 +120,6 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.pcmCruise = False
|
||||
ret.openpilotLongitudinalControl = True
|
||||
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG
|
||||
ret.customStockLongAvailable = True
|
||||
|
||||
else: # ASCM, OBD-II harness
|
||||
ret.openpilotLongitudinalControl = True
|
||||
@@ -205,6 +205,8 @@ class CarInterface(CarInterfaceBase):
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_loopback)
|
||||
|
||||
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:
|
||||
self.CS.button_events = [
|
||||
@@ -213,19 +215,21 @@ class CarInterface(CarInterfaceBase):
|
||||
*create_button_events(self.CS.distance_button, self.CS.prev_distance_button,
|
||||
{1: ButtonType.gapAdjustCruise})
|
||||
]
|
||||
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.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 self.CS.button_events):
|
||||
self.CS.accEnabled = True
|
||||
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, c.vCruise, self.CS.accEnabled)
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
self.CS.button_events, c.vCruise)
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if self.enable_mads:
|
||||
@@ -233,15 +237,15 @@ class CarInterface(CarInterfaceBase):
|
||||
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, 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 not self.CP.pcmCruise or (self.CP.pcmCruise and self.CP.minEnableSpeed > 0):
|
||||
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
|
||||
self.get_sp_cancel_cruise_state()
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.get_sp_cancel_cruise_state()
|
||||
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
|
||||
|
||||
if self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed:
|
||||
@@ -249,7 +253,7 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.accEnabled = False
|
||||
self.CS.accEnabled = ret.cruiseState.enabled or self.CS.accEnabled
|
||||
|
||||
ret = self.get_sp_common_state(ret)
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=bool(distance_button))
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -264,7 +268,7 @@ class CarInterface(CarInterfaceBase):
|
||||
# if any(b.type == ButtonType.accelCruise and b.pressed for b in ret.buttonEvents):
|
||||
# events.add(EventName.buttonEnable)
|
||||
|
||||
events, ret = self.create_sp_events(ret, events, enable_pressed=self.CS.accEnabled,
|
||||
events, ret = self.create_sp_events(self.CS, ret, events, enable_pressed=self.CS.accEnabled,
|
||||
enable_buttons=(ButtonType.decelCruise,))
|
||||
|
||||
# Enabling at a standstill with brake is allowed
|
||||
@@ -278,8 +282,6 @@ class CarInterface(CarInterfaceBase):
|
||||
if ret.vEgo < self.CP.minSteerSpeed and self.CS.madsEnabled:
|
||||
events.add(EventName.belowSteerSpeed)
|
||||
|
||||
ret.customStockLong = self.update_custom_stock_long()
|
||||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
return ret
|
||||
|
||||
@@ -5,12 +5,13 @@ 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 DT_CTRL, rate_limit, make_tester_present_msg, create_gas_interceptor_command
|
||||
from openpilot.selfdrive.car import 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 HONDA_V_CRUISE_MIN
|
||||
from openpilot.selfdrive.controls.lib.drive_helpers import rate_limit, HONDA_V_CRUISE_MIN
|
||||
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
LongCtrlState = car.CarControl.Actuators.LongControlState
|
||||
@@ -109,10 +110,11 @@ def rate_limit_steer(new_steer, last_steer):
|
||||
|
||||
class CarController(CarControllerBase):
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
super().__init__(dbc_name, CP, VM)
|
||||
self.CP = CP
|
||||
self.packer = CANPacker(dbc_name)
|
||||
self.params = CarControllerParams(CP)
|
||||
self.CAN = hondacan.CanBus(CP)
|
||||
self.frame = 0
|
||||
|
||||
self.braking = False
|
||||
self.brake_steady = 0.
|
||||
@@ -222,7 +224,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(make_tester_present_msg(0x18DAB0F1, 1, suppress_response=True))
|
||||
can_sends.append((0x18DAB0F1, 0, b"\x02\x3E\x80\x00\x00\x00\x00\x00", 1))
|
||||
|
||||
# Send steering command.
|
||||
can_sends.append(hondacan.create_steering_control(self.packer, self.CAN, apply_steer, CC.latActive, self.CP.carFingerprint,
|
||||
|
||||
@@ -576,7 +576,6 @@ 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',
|
||||
|
||||
@@ -267,9 +267,10 @@ class CarInterface(CarInterfaceBase):
|
||||
*create_button_events(self.CS.cruise_setting, self.CS.prev_cruise_setting, SETTINGS_BUTTONS_DICT),
|
||||
]
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret)
|
||||
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, c.vCruise, self.CS.accEnabled)
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
self.CS.button_events, c.vCruise)
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if self.enable_mads:
|
||||
@@ -277,7 +278,7 @@ class CarInterface(CarInterfaceBase):
|
||||
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, self.CS.madsEnabled)
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
else:
|
||||
self.CS.madsEnabled = False
|
||||
|
||||
@@ -285,9 +286,9 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
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.get_sp_cancel_cruise_state()
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.get_sp_cancel_cruise_state()
|
||||
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 or min_enable_speed_pcm \
|
||||
else False if self.CP.pcmCruise \
|
||||
else self.CS.accEnabled
|
||||
@@ -300,7 +301,7 @@ class CarInterface(CarInterfaceBase):
|
||||
elif not ret.cruiseState.enabled:
|
||||
self.CS.accEnabled = False
|
||||
|
||||
ret = self.get_sp_common_state(ret)
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=(self.CS.cruise_setting == 3))
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -312,7 +313,7 @@ class CarInterface(CarInterfaceBase):
|
||||
if self.CP.pcmCruise and ret.vEgo < self.CP.minEnableSpeed and not self.CS.madsEnabled:
|
||||
events.add(EventName.belowEngageSpeed)
|
||||
|
||||
events, ret = self.create_sp_events(ret, events)
|
||||
events, ret = self.create_sp_events(self.CS, ret, events)
|
||||
|
||||
#if self.CP.pcmCruise:
|
||||
# # we engage when pcm is active (rising edge)
|
||||
@@ -329,7 +330,9 @@ class CarInterface(CarInterfaceBase):
|
||||
if self.CS.CP.minEnableSpeed > 0 and ret.vEgo < 0.001:
|
||||
events.add(EventName.manualRestart)
|
||||
|
||||
ret.customStockLong = self.update_custom_stock_long()
|
||||
ret.customStockLong = self.CS.update_custom_stock_long(self.CC.cruise_button, self.CC.final_speed_kph,
|
||||
self.CC.target_speed, self.CC.v_set_dis,
|
||||
self.CC.speed_diff, self.CC.button_type)
|
||||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from cereal import car
|
||||
import cereal.messaging as messaging
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
from openpilot.common.numpy_fast import clip, interp
|
||||
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 DT_CTRL, apply_driver_steer_torque_limits, common_fault_avoidance, make_tester_present_msg
|
||||
from openpilot.selfdrive.car import apply_driver_steer_torque_limits, common_fault_avoidance
|
||||
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
|
||||
@@ -47,11 +48,12 @@ def process_hud_alert(enabled, fingerprint, hud_control):
|
||||
|
||||
class CarController(CarControllerBase):
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
super().__init__(dbc_name, CP, VM)
|
||||
self.CP = CP
|
||||
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
|
||||
@@ -62,7 +64,7 @@ class CarController(CarControllerBase):
|
||||
self.lat_disengage_init = False
|
||||
self.lat_active_last = False
|
||||
|
||||
sub_services = ['longitudinalPlan', 'longitudinalPlanSP']
|
||||
sub_services = ['longitudinalPlanSP']
|
||||
if CP.openpilotLongitudinalControl:
|
||||
sub_services.append('radarState')
|
||||
# TODO: Always true, prep for future conditional refactoring
|
||||
@@ -94,24 +96,9 @@ class CarController(CarControllerBase):
|
||||
self.v_tsc = 0
|
||||
self.m_tsc = 0
|
||||
self.steady_speed = 0
|
||||
self.speeds = 0
|
||||
self.v_target_plan = 0
|
||||
self.custom_stock_planner_speed = self.param_s.get_bool("CustomStockLongPlanner")
|
||||
self.hkg_can_smooth_stop = self.param_s.get_bool("HkgSmoothStop")
|
||||
self.lead_distance = 0
|
||||
|
||||
self.jerk = 0.0
|
||||
self.jerk_l = 0.0
|
||||
self.jerk_u = 0.0
|
||||
self.jerkStartLimit = 2.0
|
||||
self.cb_upper = 0.0
|
||||
self.cb_lower = 0.0
|
||||
self.jerk_count = 0.0
|
||||
|
||||
self.accel_raw = 0
|
||||
self.accel_val = 0
|
||||
self.accel_last_jerk = 0
|
||||
self.hkg_custom_long_tuning = self.param_s.get_bool("HkgCustomLongTuning")
|
||||
|
||||
def calculate_lead_distance(self, hud_control: car.CarControl.HUDControl) -> float:
|
||||
lead_one = self.sm["radarState"].leadOne
|
||||
lead_two = self.sm["radarState"].leadTwo
|
||||
@@ -128,10 +115,6 @@ class CarController(CarControllerBase):
|
||||
self.sm.update(0)
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if self.sm.updated['longitudinalPlan']:
|
||||
_speeds = self.sm['longitudinalPlan'].speeds
|
||||
self.speeds = _speeds[-1] if len(_speeds) else 0
|
||||
|
||||
if self.sm.updated['longitudinalPlanSP']:
|
||||
self.v_tsc_state = self.sm['longitudinalPlanSP'].visionTurnControllerState
|
||||
self.slc_state = self.sm['longitudinalPlanSP'].speedLimitControlState
|
||||
@@ -141,21 +124,14 @@ class CarController(CarControllerBase):
|
||||
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
|
||||
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
|
||||
|
||||
if self.frame % 200 == 0:
|
||||
self.custom_stock_planner_speed = self.param_s.get_bool("CustomStockLongPlanner")
|
||||
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)
|
||||
self.v_target_plan = min(CC.vCruise * CV.KPH_TO_MS, self.speeds)
|
||||
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
|
||||
# steering torque
|
||||
if self.CP.spFlags & HyundaiFlagsSP.SP_UPSTREAM_TACO.value:
|
||||
self.params = CarControllerParams(self.CP, CS.out.vEgoRaw)
|
||||
new_steer = int(round(actuators.steer * self.params.STEER_MAX))
|
||||
apply_steer = apply_driver_steer_torque_limits(new_steer, self.apply_steer_last, CS.out.steeringTorque, self.params)
|
||||
if self.CP.spFlags & HyundaiFlagsSP.SP_UPSTREAM_TACO.value:
|
||||
apply_steer = clip(apply_steer, -self.params.STEER_MAX, self.params.STEER_MAX)
|
||||
|
||||
# >90 degree steering fault prevention
|
||||
self.angle_limit_counter, apply_steer_req = common_fault_avoidance(abs(CS.out.steeringAngleDeg) >= MAX_ANGLE, CC.latActive,
|
||||
@@ -216,17 +192,14 @@ class CarController(CarControllerBase):
|
||||
if self.frame % 100 == 0 and not ((self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value) or escc) and \
|
||||
self.CP.carFingerprint not in CAMERA_SCC_CAR and self.CP.openpilotLongitudinalControl:
|
||||
# for longitudinal control, either radar or ADAS driving ECU
|
||||
addr, bus = 0x7d0, self.CAN.ECAN if self.CP.carFingerprint in CANFD_CAR else 0
|
||||
addr, bus = 0x7d0, 0
|
||||
if self.CP.flags & HyundaiFlags.CANFD_HDA2.value:
|
||||
addr, bus = 0x730, self.CAN.ECAN
|
||||
can_sends.append(make_tester_present_msg(addr, bus, suppress_response=True))
|
||||
can_sends.append([addr, 0, b"\x02\x3E\x80\x00\x00\x00\x00\x00", bus])
|
||||
|
||||
# for blinkers
|
||||
if self.CP.flags & HyundaiFlags.ENABLE_BLINKERS:
|
||||
can_sends.append(make_tester_present_msg(0x7b1, self.CAN.ECAN, suppress_response=True))
|
||||
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
self.make_jerk(CS, accel, actuators)
|
||||
can_sends.append([0x7b1, 0, b"\x02\x3E\x80\x00\x00\x00\x00\x00", self.CAN.ECAN])
|
||||
|
||||
# CAN-FD platforms
|
||||
if self.CP.carFingerprint in CANFD_CAR:
|
||||
@@ -254,11 +227,9 @@ class CarController(CarControllerBase):
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
if hda2:
|
||||
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
|
||||
else:
|
||||
can_sends.extend(hyundaicanfd.create_fca_warning_light(self.packer, self.CAN, self.frame))
|
||||
if self.frame % 2 == 0:
|
||||
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.jerk_u, self.jerk_l))
|
||||
set_speed_in_units, hud_control))
|
||||
self.accel_last = accel
|
||||
else:
|
||||
# button presses
|
||||
@@ -302,13 +273,15 @@ class CarController(CarControllerBase):
|
||||
self.lead_distance = self.calculate_lead_distance(hud_control)
|
||||
|
||||
if self.frame % 2 == 0 and self.CP.openpilotLongitudinalControl:
|
||||
if self.hkg_can_smooth_stop:
|
||||
stopping = stopping and CS.out.vEgoRaw < 0.05
|
||||
|
||||
# TODO: unclear if this is needed
|
||||
jerk = 3.0 if actuators.longControlState == LongCtrlState.pid else 1.0
|
||||
use_fca = self.CP.flags & HyundaiFlags.USE_FCA.value
|
||||
self.make_accel(CS, actuators)
|
||||
can_sends.extend(hyundaican.create_acc_commands(self.packer, CC.enabled and CS.out.cruiseState.enabled, self.accel_raw, self.accel_val, self.jerk_l, self.jerk_u, int(self.frame / 2),
|
||||
can_sends.extend(hyundaican.create_acc_commands(self.packer, CC.enabled and CS.out.cruiseState.enabled, accel, jerk, int(self.frame / 2),
|
||||
hud_control, set_speed_in_units, stopping,
|
||||
CC.cruiseControl.override, use_fca, CS, escc, self.CP, self.lead_distance, self.cb_lower, self.cb_upper))
|
||||
CC.cruiseControl.override, use_fca, CS, escc, self.CP, self.lead_distance))
|
||||
|
||||
# 20 Hz LFA MFA message
|
||||
if self.frame % 5 == 0 and self.CP.flags & HyundaiFlags.SEND_LFA.value:
|
||||
@@ -475,8 +448,6 @@ class CarController(CarControllerBase):
|
||||
target_speed_kph = set_speed_kph
|
||||
else:
|
||||
target_speed_kph = min(v_cruise_kph_prev, set_speed_kph)
|
||||
if self.custom_stock_planner_speed:
|
||||
target_speed_kph = self.curve_speed_hysteresis(self.v_target_plan * CV.MS_TO_KPH)
|
||||
if self.v_tsc_state != 0 or self.m_tsc_state > 1:
|
||||
self.final_speed_kph = self.get_curve_speed(target_speed_kph, v_cruise_kph_prev)
|
||||
else:
|
||||
@@ -484,66 +455,3 @@ class CarController(CarControllerBase):
|
||||
|
||||
cruise_button = self.get_button_control(CS, self.final_speed_kph, v_cruise_kph_prev) # MPH/KPH based button presses
|
||||
return cruise_button
|
||||
|
||||
# jerk calculations thanks to apilot!
|
||||
def cal_jerk(self, accel, actuators):
|
||||
self.accel_raw = accel
|
||||
if actuators.longControlState == LongCtrlState.off:
|
||||
accel_diff = 0.0
|
||||
elif actuators.longControlState == LongCtrlState.stopping:# or hud_control.softHold > 0:
|
||||
accel_diff = 0.0
|
||||
else:
|
||||
accel_diff = self.accel_raw - self.accel_last_jerk
|
||||
|
||||
accel_diff /= DT_CTRL
|
||||
self.jerk = self.jerk * 0.9 + accel_diff * 0.1
|
||||
return self.jerk
|
||||
|
||||
def make_jerk(self, CS, accel, actuators):
|
||||
jerk = self.cal_jerk(accel, actuators)
|
||||
a_error = accel - CS.out.aEgo
|
||||
jerk = jerk + (a_error * 2.0)
|
||||
|
||||
if not self.hkg_custom_long_tuning:
|
||||
self.jerk_u = 3.0 if actuators.longControlState == LongCtrlState.pid else 1.0
|
||||
self.jerk_l = 5.0
|
||||
elif True: #self.CP.carFingerprint in CANFD_CAR or self.CP.carFingerprint == CAR.HYUNDAI_KONA_EV_2022:
|
||||
startingJerk = 0.5
|
||||
jerkLimit = 5.0
|
||||
self.jerk_count += DT_CTRL
|
||||
jerk_max = interp(self.jerk_count, [0, 1.5, 2.5], [startingJerk, startingJerk, jerkLimit])
|
||||
if actuators.longControlState == LongCtrlState.off:
|
||||
self.jerk_u = jerkLimit
|
||||
self.jerk_l = jerkLimit
|
||||
self.jerk_count = 0
|
||||
else:
|
||||
self.jerk_u = min(max(0.5, jerk * 2.0), jerk_max)
|
||||
self.jerk_l = min(max(1.0, -jerk * 3.0), jerkLimit)
|
||||
else:
|
||||
startingJerk = self.jerkStartLimit
|
||||
jerkLimit = 5.0
|
||||
self.jerk_count += DT_CTRL
|
||||
jerk_max = interp(self.jerk_count, [0, 1.5, 2.5], [startingJerk, startingJerk, jerkLimit])
|
||||
self.cb_upper = self.cb_lower = 0
|
||||
if actuators.longControlState == LongCtrlState.off:
|
||||
self.jerk_u = jerkLimit
|
||||
self.jerk_l = jerkLimit
|
||||
self.jerk_count = 0
|
||||
else:
|
||||
self.jerk_u = min(max(0.5, jerk * 2.0), jerk_max)
|
||||
self.jerk_l = min(max(0.5, -jerk * 2.0), jerkLimit)
|
||||
self.cb_upper = clip(0.9 + accel * 0.2, 0, 1.2)
|
||||
self.cb_lower = clip(0.8 + accel * 0.2, 0, 1.2)
|
||||
|
||||
def make_accel(self, CS, actuators):
|
||||
long_control = actuators.longControlState
|
||||
is_ice = not self.CP.flags & (HyundaiFlags.HYBRID | HyundaiFlags.EV)
|
||||
rate_up = 0.1
|
||||
rate_down = 0.1
|
||||
if long_control == LongCtrlState.off or (long_control == LongCtrlState.stopping and CS.out.standstill):
|
||||
self.accel_raw, self.accel_val = 0, 0
|
||||
else:
|
||||
#self.accel_val = clip(self.accel_raw, self.accel_last - rate_down, self.accel_last + rate_up)
|
||||
self.accel_val = self.accel_raw
|
||||
self.accel_last = self.accel_val
|
||||
self.accel_last_jerk = self.accel_val
|
||||
|
||||
@@ -171,7 +171,6 @@ 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',
|
||||
@@ -292,7 +291,6 @@ 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',
|
||||
],
|
||||
@@ -409,7 +407,6 @@ 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',
|
||||
@@ -483,13 +480,11 @@ 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',
|
||||
@@ -590,7 +585,6 @@ 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',
|
||||
],
|
||||
@@ -601,7 +595,6 @@ 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',
|
||||
],
|
||||
@@ -712,7 +705,6 @@ 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 ',
|
||||
],
|
||||
},
|
||||
@@ -765,12 +757,10 @@ 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: {
|
||||
@@ -1171,17 +1161,6 @@ FW_VERSIONS = {
|
||||
b'\xf1\x006T6J0_C2\x00\x006T6K1051\x00\x00TOS4N20NS2\x00\x00\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_KONA_EV_NON_SCC: {
|
||||
(Ecu.abs, 0x7d1, None): [
|
||||
b'\xf1\x00OS IEB \x02 212 \x11\x13 58520-K4000',
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00OS MDPS C 1.00 1.04 56310K4000\x00 4OEDC104',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00OSE LKAS AT USA LHD 1.00 1.00 95740-K4100 W40',
|
||||
],
|
||||
},
|
||||
CAR.KIA_CEED_PHEV_2022_NON_SCC: {
|
||||
(Ecu.eps, 0x7D4, None): [
|
||||
b'\xf1\x00CD MDPS C 1.00 1.01 56310-XX000 4CPHC101',
|
||||
|
||||
@@ -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)[1]
|
||||
dat = packer.make_can_msg("LKAS11", 0, values)[2]
|
||||
|
||||
if CP.flags & HyundaiFlags.CHECKSUM_CRC8:
|
||||
# CRC Checksum as seen on 2019 Hyundai Santa Fe
|
||||
@@ -130,8 +130,8 @@ def create_lfahda_mfc(packer, enabled, lat_active, lateral_paused, blinking_icon
|
||||
}
|
||||
return packer.make_can_msg("LFAHDA_MFC", 0, values)
|
||||
|
||||
def create_acc_commands(packer, enabled, accel_raw, accel_val, lower_jerk, upper_jerk, idx, hud_control, set_speed, stopping, long_override, use_fca,
|
||||
CS, escc, CP, lead_distance, cb_lower, cb_upper):
|
||||
def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, set_speed, stopping, long_override, use_fca,
|
||||
CS, escc, CP, lead_distance):
|
||||
commands = []
|
||||
|
||||
scc11_values = {
|
||||
@@ -150,8 +150,8 @@ def create_acc_commands(packer, enabled, accel_raw, accel_val, lower_jerk, upper
|
||||
scc12_values = {
|
||||
"ACCMode": 2 if enabled and long_override else 1 if enabled else 0,
|
||||
"StopReq": 1 if stopping else 0,
|
||||
"aReqRaw": accel_raw,
|
||||
"aReqValue": accel_val, # stock ramps up and down respecting jerk limit until it reaches aReqRaw
|
||||
"aReqRaw": accel,
|
||||
"aReqValue": accel, # stock ramps up and down respecting jerk limit until it reaches aReqRaw
|
||||
"CR_VSM_Alive": idx % 0xF,
|
||||
}
|
||||
|
||||
@@ -166,16 +166,16 @@ def create_acc_commands(packer, enabled, accel_raw, accel_val, lower_jerk, upper
|
||||
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)[1]
|
||||
scc12_dat = packer.make_can_msg("SCC12", 0, scc12_values)[2]
|
||||
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))
|
||||
|
||||
scc14_values = {
|
||||
"ComfortBandUpper": cb_upper, # stock usually is 0 but sometimes uses higher values
|
||||
"ComfortBandLower": cb_lower, # stock usually is 0 but sometimes uses higher values
|
||||
"ComfortBandUpper": 0.0, # stock usually is 0 but sometimes uses higher values
|
||||
"ComfortBandLower": 0.0, # stock usually is 0 but sometimes uses higher values
|
||||
"JerkUpperLimit": upper_jerk, # stock usually is 1.0 but sometimes uses higher values
|
||||
"JerkLowerLimit": lower_jerk, # stock usually is 0.5 but sometimes uses higher values
|
||||
"JerkLowerLimit": 5.0, # stock usually is 0.5 but sometimes uses higher values
|
||||
"ACCMode": 2 if enabled and long_override else 1 if enabled else 4, # stock will always be 4 instead of 0 after first disengage
|
||||
"ObjGap": get_object_gap(lead_distance), # 5: >30, m, 4: 25-30 m, 3: 20-25 m, 2: < 20 m, 0: no lead
|
||||
}
|
||||
@@ -197,7 +197,7 @@ def create_acc_commands(packer, enabled, accel_raw, accel_val, lower_jerk, upper
|
||||
"FCA_DrvSetStatus": 1,
|
||||
"FCA_Status": 1, # AEB disabled
|
||||
}
|
||||
fca11_dat = packer.make_can_msg("FCA11", 0, fca11_values)[1]
|
||||
fca11_dat = packer.make_can_msg("FCA11", 0, fca11_values)[2]
|
||||
fca11_values["CR_FCA_ChkSum"] = hyundai_checksum(fca11_dat[:7])
|
||||
commands.append(packer.make_can_msg("FCA11", 0, fca11_values))
|
||||
|
||||
@@ -207,7 +207,7 @@ def create_acc_opt(packer, escc, CS, CP):
|
||||
commands = []
|
||||
|
||||
scc13_values = {
|
||||
"SCCDrvModeRValue": 3,
|
||||
"SCCDrvModeRValue": 2,
|
||||
"SCC_Equip": 1,
|
||||
"Lead_Veh_Dep_Alert_USM": 2,
|
||||
}
|
||||
|
||||
@@ -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, CS, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control, upper_jerk, lower_jerk):
|
||||
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:
|
||||
@@ -137,8 +137,8 @@ def create_acc_control(packer, CAN, CS, enabled, accel_last, accel, stopping, ga
|
||||
"aReqValue": a_val,
|
||||
"aReqRaw": a_raw,
|
||||
"VSetDis": set_speed,
|
||||
"JerkLowerLimit": lower_jerk,
|
||||
"JerkUpperLimit": upper_jerk,
|
||||
"JerkLowerLimit": jerk if enabled else 1,
|
||||
"JerkUpperLimit": 3.0,
|
||||
|
||||
"ACC_ObjDist": 1,
|
||||
"ObjValid": 0,
|
||||
@@ -172,20 +172,6 @@ def create_spas_messages(packer, CAN, frame, left_blink, right_blink):
|
||||
return ret
|
||||
|
||||
|
||||
def create_fca_warning_light(packer, CAN, frame):
|
||||
ret = []
|
||||
if frame % 2 == 0:
|
||||
values = {
|
||||
'AEB_SETTING': 0x1, # show AEB disabled icon
|
||||
'SET_ME_2': 0x2,
|
||||
'SET_ME_FF': 0xff,
|
||||
'SET_ME_FC': 0xfc,
|
||||
'SET_ME_9': 0x9,
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x160", CAN.ECAN, values))
|
||||
return ret
|
||||
|
||||
|
||||
def create_adrv_messages(packer, CAN, frame):
|
||||
# messages needed to car happy after disabling
|
||||
# the ADAS Driving ECU to do longitudinal control
|
||||
@@ -196,7 +182,15 @@ def create_adrv_messages(packer, CAN, frame):
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x51", CAN.ACAN, values))
|
||||
|
||||
ret.extend(create_fca_warning_light(packer, CAN, frame))
|
||||
if frame % 2 == 0:
|
||||
values = {
|
||||
'AEB_SETTING': 0x1, # show AEB disabled icon
|
||||
'SET_ME_2': 0x2,
|
||||
'SET_ME_FF': 0xff,
|
||||
'SET_ME_FC': 0xfc,
|
||||
'SET_ME_9': 0x9,
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x160", CAN.ECAN, values))
|
||||
|
||||
if frame % 5 == 0:
|
||||
values = {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import cereal.messaging as messaging
|
||||
from cereal import car
|
||||
from panda import Panda
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.selfdrive.car.sunnypilot.fingerprinting import can_fingerprint, get_one_can
|
||||
from openpilot.selfdrive.car.hyundai.enable_radar_tracks import enable_radar_tracks
|
||||
from openpilot.selfdrive.car.hyundai.hyundaicanfd import CanBus
|
||||
from openpilot.selfdrive.car.hyundai.values import HyundaiFlags, HyundaiFlagsSP, CAR, DBC, CANFD_CAR, CAMERA_SCC_CAR, CANFD_RADAR_SCC_CAR, \
|
||||
@@ -93,7 +91,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# *** longitudinal control ***
|
||||
if candidate in CANFD_CAR:
|
||||
ret.experimentalLongitudinalAvailable = candidate not in (CANFD_UNSUPPORTED_LONGITUDINAL_CAR | NON_SCC_CAR)
|
||||
ret.experimentalLongitudinalAvailable = candidate not in (CANFD_UNSUPPORTED_LONGITUDINAL_CAR | CANFD_RADAR_SCC_CAR | NON_SCC_CAR)
|
||||
if ret.flags & HyundaiFlags.CANFD_CAMERA_SCC and not hda2:
|
||||
ret.spFlags |= HyundaiFlagsSP.SP_CAMERA_SCC_LEAD.value
|
||||
else:
|
||||
@@ -104,20 +102,13 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.pcmCruise = not ret.openpilotLongitudinalControl
|
||||
|
||||
ret.stoppingControl = True
|
||||
ret.startingState = True
|
||||
ret.vEgoStarting = 0.1
|
||||
ret.startAccel = 1.6
|
||||
ret.startAccel = 1.0
|
||||
ret.longitudinalActuatorDelay = 0.5
|
||||
|
||||
if ret.flags & (HyundaiFlags.HYBRID | HyundaiFlags.EV):
|
||||
ret.startingState = False
|
||||
ret.stopAccel = -2.0
|
||||
else:
|
||||
ret.startingState = True
|
||||
ret.stopAccel = -1.0
|
||||
|
||||
if DBC[ret.carFingerprint]["radar"] is None:
|
||||
if ret.spFlags & (HyundaiFlagsSP.SP_ENHANCED_SCC | HyundaiFlagsSP.SP_CAMERA_SCC_LEAD):
|
||||
ret.radarTimeStep = 0.02
|
||||
ret.radarUnavailable = False
|
||||
|
||||
# *** feature detection ***
|
||||
@@ -126,8 +117,6 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
if 0x1fa in fingerprint[CAN.ECAN]:
|
||||
ret.spFlags |= HyundaiFlagsSP.SP_NAV_MSG.value
|
||||
if Params().get("DongleId", encoding='utf8') in ("012c95f06918eca4", "68d6a96e703c00c9", "11c1f1909ca37bca"):
|
||||
ret.spFlags |= HyundaiFlagsSP.SP_UPSTREAM_TACO.value
|
||||
else:
|
||||
ret.enableBsm = 0x58b in fingerprint[0]
|
||||
|
||||
@@ -136,8 +125,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
if ret.flags & HyundaiFlags.MANDO_RADAR and ret.radarUnavailable:
|
||||
ret.spFlags |= HyundaiFlagsSP.SP_RADAR_TRACKS.value
|
||||
if Params().get_bool("HyundaiRadarTracksAvailable"):
|
||||
ret.radarUnavailable = False
|
||||
ret.radarUnavailable = False
|
||||
|
||||
# *** panda safety config ***
|
||||
if candidate in CANFD_CAR:
|
||||
@@ -154,8 +142,6 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_HYUNDAI_CANFD_ALT_BUTTONS
|
||||
if ret.flags & HyundaiFlags.CANFD_CAMERA_SCC:
|
||||
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_HYUNDAI_CAMERA_SCC
|
||||
if ret.spFlags & HyundaiFlagsSP.SP_UPSTREAM_TACO:
|
||||
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_HYUNDAI_UPSTREAM_TACO
|
||||
else:
|
||||
if candidate in LEGACY_SAFETY_MODE_CAR:
|
||||
# these cars require a special panda safety mode due to missing counters and checksums in the messages
|
||||
@@ -181,8 +167,7 @@ class CarInterface(CarInterfaceBase):
|
||||
elif ret.flags & HyundaiFlags.EV:
|
||||
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_HYUNDAI_EV_GAS
|
||||
|
||||
if candidate in (CAR.HYUNDAI_KONA, CAR.HYUNDAI_KONA_EV, CAR.HYUNDAI_KONA_HEV, CAR.HYUNDAI_KONA_EV_2022,
|
||||
CAR.HYUNDAI_KONA_NON_SCC, CAR.HYUNDAI_KONA_EV_NON_SCC):
|
||||
if candidate in (CAR.HYUNDAI_KONA, CAR.HYUNDAI_KONA_EV, CAR.HYUNDAI_KONA_HEV, CAR.HYUNDAI_KONA_EV_2022, CAR.HYUNDAI_KONA_NON_SCC):
|
||||
ret.flags |= HyundaiFlags.ALT_LIMITS.value
|
||||
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_HYUNDAI_ALT_LIMITS
|
||||
|
||||
@@ -192,13 +177,16 @@ class CarInterface(CarInterfaceBase):
|
||||
if 0x2AA in fingerprint[0]:
|
||||
ret.minSteerSpeed = 0.
|
||||
|
||||
if Params().get_bool("HkgSmoothStop"):
|
||||
ret.vEgoStopping = 0.1
|
||||
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def init(CP, logcan, sendcan):
|
||||
if CP.openpilotLongitudinalControl and not ((CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value) or (CP.spFlags & HyundaiFlagsSP.SP_ENHANCED_SCC)) and \
|
||||
CP.carFingerprint not in CAMERA_SCC_CAR:
|
||||
addr, bus = 0x7d0, CanBus(CP).ECAN if CP.carFingerprint in CANFD_CAR else 0
|
||||
addr, bus = 0x7d0, 0
|
||||
if CP.flags & HyundaiFlags.CANFD_HDA2.value:
|
||||
addr, bus = 0x730, CanBus(CP).ECAN
|
||||
disable_ecu(logcan, sendcan, bus=bus, addr=addr, com_cont_req=b'\x28\x83\x01')
|
||||
@@ -213,23 +201,7 @@ class CarInterface(CarInterfaceBase):
|
||||
if CP.spFlags & HyundaiFlagsSP.SP_RADAR_TRACKS:
|
||||
enable_radar_tracks(logcan, sendcan, bus=0, addr=0x7d0, config_data_id=b'\x01\x42')
|
||||
|
||||
params = Params()
|
||||
rt_avail = params.get_bool("HyundaiRadarTracksAvailable")
|
||||
rt_avail_persist = params.get_bool("HyundaiRadarTracksAvailablePersistent")
|
||||
params.put_bool_nonblocking("HyundaiRadarTracksAvailableCache", rt_avail)
|
||||
if not rt_avail_persist:
|
||||
messaging.drain_sock_raw(logcan)
|
||||
fingerprint = can_fingerprint(lambda: get_one_can(logcan))
|
||||
radar_unavailable = RADAR_START_ADDR not in fingerprint[1] or DBC[CP.carFingerprint]["radar"] is None
|
||||
params.put_bool_nonblocking("HyundaiRadarTracksAvailable", not radar_unavailable)
|
||||
params.put_bool_nonblocking("HyundaiRadarTracksAvailablePersistent", True)
|
||||
|
||||
def _update(self, c):
|
||||
if not self.CS.control_initialized and not self.CP.pcmCruise:
|
||||
can_cruise_main_default = self.CP.spFlags & HyundaiFlagsSP.SP_CAN_LFA_BTN and not self.CP.flags & HyundaiFlags.CANFD and \
|
||||
self.CS.params_list.hyundai_cruise_main_default
|
||||
self.CS.mainEnabled = True if can_cruise_main_default or self.CP.carFingerprint in CANFD_CAR else False
|
||||
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
|
||||
self.CS.button_events = [
|
||||
@@ -238,9 +210,10 @@ class CarInterface(CarInterfaceBase):
|
||||
*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.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, c.vCruise, self.CS.accEnabled)
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
self.CS.button_events, c.vCruise)
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
@@ -248,12 +221,12 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.accEnabled = True
|
||||
|
||||
if self.enable_mads:
|
||||
if not self.CS.prev_mads_enabled and self.CS.mads_enabled and (self.CP.pcmCruise or
|
||||
(any(b.type == ButtonType.altButton3 for b in self.CS.button_events) and not self.CP.pcmCruise)):
|
||||
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, 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
|
||||
@@ -261,15 +234,15 @@ class CarInterface(CarInterfaceBase):
|
||||
if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed:
|
||||
if not self.CP.pcmCruise:
|
||||
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
|
||||
self.get_sp_cancel_cruise_state()
|
||||
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:
|
||||
self.get_sp_cancel_cruise_state()
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.get_sp_cancel_cruise_state()
|
||||
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 = self.get_sp_common_state(ret)
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=(self.CS.cruise_buttons[-1] == 3))
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -283,7 +256,7 @@ class CarInterface(CarInterfaceBase):
|
||||
events = self.create_common_events(ret, c, extra_gears=[GearShifter.sport, GearShifter.low, GearShifter.manumatic],
|
||||
pcm_enable=False, allow_enable=allow_enable)
|
||||
|
||||
events, ret = self.create_sp_events(ret, events, main_enabled=True, allow_enable=allow_enable)
|
||||
events, ret = self.create_sp_events(self.CS, ret, events, main_enabled=True, allow_enable=allow_enable)
|
||||
|
||||
# low speed steer alert hysteresis logic (only for cars with steer cut off above 10 m/s)
|
||||
if ret.vEgo < (self.CP.minSteerSpeed + 2.) and self.CP.minSteerSpeed > 10.:
|
||||
@@ -293,10 +266,9 @@ class CarInterface(CarInterfaceBase):
|
||||
if self.low_speed_alert and self.CS.madsEnabled:
|
||||
events.add(car.CarEvent.EventName.belowSteerSpeed)
|
||||
|
||||
if self.CS.params_list.hyundai_radar_tracks_available and not self.CS.params_list.hyundai_radar_tracks_available_cache:
|
||||
events.add(car.CarEvent.EventName.hyundaiRadarTracksAvailable)
|
||||
|
||||
ret.customStockLong = self.update_custom_stock_long()
|
||||
ret.customStockLong = self.CS.update_custom_stock_long(self.CC.cruise_button, self.CC.final_speed_kph,
|
||||
self.CC.target_speed, self.CC.v_set_dis,
|
||||
self.CC.speed_diff, self.CC.button_type)
|
||||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ from dataclasses import dataclass, field
|
||||
from enum import Enum, IntFlag
|
||||
|
||||
from cereal import car
|
||||
from panda.python import uds, Panda
|
||||
from panda.python import uds
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
from openpilot.selfdrive.car import CarSpecs, DbcDict, PlatformConfig, Platforms, dbc_dict
|
||||
from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarDocs, CarParts, Column
|
||||
@@ -16,7 +16,7 @@ class CarControllerParams:
|
||||
ACCEL_MIN = -3.5 # m/s
|
||||
ACCEL_MAX = 2.0 # m/s
|
||||
|
||||
def __init__(self, CP, vEgoRaw=100.):
|
||||
def __init__(self, CP):
|
||||
self.STEER_DELTA_UP = 3
|
||||
self.STEER_DELTA_DOWN = 7
|
||||
self.STEER_DRIVER_ALLOWANCE = 50
|
||||
@@ -26,13 +26,12 @@ class CarControllerParams:
|
||||
self.STEER_STEP = 1 # 100 Hz
|
||||
|
||||
if CP.carFingerprint in CANFD_CAR:
|
||||
upstream_taco = CP.safetyConfigs[-1].safetyParam & Panda.FLAG_HYUNDAI_UPSTREAM_TACO
|
||||
self.STEER_MAX = 270 if not upstream_taco else 384 if vEgoRaw < 11. else 330
|
||||
self.STEER_DRIVER_ALLOWANCE = 250 if not upstream_taco else 350
|
||||
self.STEER_MAX = 270
|
||||
self.STEER_DRIVER_ALLOWANCE = 250
|
||||
self.STEER_DRIVER_MULTIPLIER = 2
|
||||
self.STEER_THRESHOLD = 250 if not upstream_taco else 350
|
||||
self.STEER_DELTA_UP = 2 if not upstream_taco else 10 if vEgoRaw < 11. else 2
|
||||
self.STEER_DELTA_DOWN = 3 if not upstream_taco else 10 if vEgoRaw < 11. else 3
|
||||
self.STEER_THRESHOLD = 250
|
||||
self.STEER_DELTA_UP = 2
|
||||
self.STEER_DELTA_DOWN = 3
|
||||
|
||||
# To determine the limit for your car, find the maximum value that the stock LKAS will request.
|
||||
# If the max stock LKAS request is <384, add your car to this list.
|
||||
@@ -109,7 +108,6 @@ class HyundaiFlagsSP(IntFlag):
|
||||
SP_CAMERA_SCC_LEAD = 2 ** 6
|
||||
SP_LKAS12 = 2 ** 7
|
||||
SP_RADAR_TRACKS = 2 ** 8
|
||||
SP_UPSTREAM_TACO = 2 ** 9
|
||||
|
||||
|
||||
class Footnote(Enum):
|
||||
@@ -576,12 +574,6 @@ class CAR(Platforms):
|
||||
HYUNDAI_KONA.specs,
|
||||
spFlags=HyundaiFlagsSP.SP_NON_SCC | HyundaiFlagsSP.SP_NON_SCC_FCA,
|
||||
)
|
||||
HYUNDAI_KONA_EV_NON_SCC = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Kona Electric Non-SCC 2019", "No Smart Cruise Control (SCC)", car_parts=CarParts.common([CarHarness.hyundai_g]))],
|
||||
HYUNDAI_KONA.specs,
|
||||
flags=HyundaiFlags.EV,
|
||||
spFlags=HyundaiFlagsSP.SP_NON_SCC | HyundaiFlagsSP.SP_NON_SCC_FCA,
|
||||
)
|
||||
KIA_CEED_PHEV_2022_NON_SCC = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia Ceed PHEV Non-SCC 2022", "No Smart Cruise Control (SCC)", car_parts=CarParts.common([CarHarness.hyundai_i]))],
|
||||
CarSpecs(mass=1650, wheelbase=2.65, steerRatio=13.75, tireStiffnessFactor=0.5),
|
||||
|
||||
@@ -18,15 +18,14 @@ 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.selfdrive.car import DT_CTRL, apply_hysteresis, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness, get_friction, STD_CARGO_KG, \
|
||||
ButtonEvents
|
||||
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, 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
|
||||
from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, V_CRUISE_UNSET, get_friction
|
||||
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
|
||||
@@ -72,7 +71,6 @@ class LatControlInputs(NamedTuple):
|
||||
aego: float
|
||||
|
||||
|
||||
SendCan = tuple[int, bytes, int]
|
||||
TorqueFromLateralAccelCallbackType = Callable[[LatControlInputs, car.CarParams.LateralTorqueTuning, float, float, bool, bool], float]
|
||||
|
||||
|
||||
@@ -244,6 +242,8 @@ class CarInterfaceBase(ABC):
|
||||
self.cruise_cancelled_btn = True
|
||||
self.prev_acc_mads_combo = False
|
||||
self.mads_event_lock = True
|
||||
self.gap_button_counter = 0
|
||||
self.experimental_mode_hold = False
|
||||
self.last_mads_init = 0.
|
||||
self.madsEnabledInit = False
|
||||
self.madsEnabledInitPrev = False
|
||||
@@ -260,7 +260,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[SendCan]]:
|
||||
def apply(self, c: car.CarControl, now_nanos: int) -> tuple[car.CarControl.Actuators, list[tuple[int, int, bytes, int]]]:
|
||||
return self.CC.update(c, self.CS, now_nanos)
|
||||
|
||||
@staticmethod
|
||||
@@ -406,7 +406,7 @@ class CarInterfaceBase(ABC):
|
||||
|
||||
@staticmethod
|
||||
def sp_configure_custom_torque_tune(ret, params):
|
||||
ret.lateralTuning.torque.friction = float(params.get("TorqueFriction", encoding="utf8")) * 0.001
|
||||
ret.lateralTuning.torque.friction = float(params.get("TorqueFriction", encoding="utf8")) * 0.01
|
||||
ret.lateralTuning.torque.latAccelFactor = float(params.get("TorqueMaxLatAccel", encoding="utf8")) * 0.01
|
||||
return ret
|
||||
|
||||
@@ -416,10 +416,9 @@ class CarInterfaceBase(ABC):
|
||||
|
||||
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_list)
|
||||
cp.update_strings(can_strings)
|
||||
|
||||
self.CS.button_events = []
|
||||
self.CS.params_list = params_list
|
||||
@@ -548,20 +547,20 @@ class CarInterfaceBase(ABC):
|
||||
def sp_v_cruise_initialized(v_cruise):
|
||||
return v_cruise != V_CRUISE_UNSET
|
||||
|
||||
def get_acc_mads(self, cs_out, mads_enabled):
|
||||
def get_acc_mads(self, cruiseState_enabled, acc_enabled, mads_enabled):
|
||||
if self.CS.params_list.acc_mads_combo:
|
||||
if not self.prev_acc_mads_combo and (cs_out.cruiseState.enabled or self.CS.accEnabled):
|
||||
if not self.prev_acc_mads_combo and (cruiseState_enabled or acc_enabled):
|
||||
mads_enabled = True
|
||||
self.prev_acc_mads_combo = (cs_out.cruiseState.enabled or self.CS.accEnabled)
|
||||
self.prev_acc_mads_combo = (cruiseState_enabled or acc_enabled)
|
||||
|
||||
return mads_enabled
|
||||
|
||||
def get_sp_v_cruise_non_pcm_state(self, cs_out, vCruise, acc_enabled,
|
||||
def get_sp_v_cruise_non_pcm_state(self, cs_out, acc_enabled, button_events, vCruise,
|
||||
enable_buttons=(ButtonType.accelCruise, ButtonType.decelCruise),
|
||||
resume_button=(ButtonType.accelCruise, ButtonType.resumeCruise)):
|
||||
|
||||
if cs_out.cruiseState.available:
|
||||
for b in self.CS.button_events:
|
||||
for b in button_events:
|
||||
if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed:
|
||||
if b.type in enable_buttons and not b.pressed:
|
||||
acc_enabled = True
|
||||
@@ -576,9 +575,9 @@ class CarInterfaceBase(ABC):
|
||||
|
||||
return acc_enabled
|
||||
|
||||
def get_sp_cancel_cruise_state(self):
|
||||
self.CS.madsEnabled = False if not self.enable_mads or self.disengage_on_accelerator else self.CS.madsEnabled
|
||||
self.CS.accEnabled = False
|
||||
def get_sp_cancel_cruise_state(self, mads_enabled, acc_enabled=False):
|
||||
mads_enabled = False if not self.enable_mads or self.disengage_on_accelerator else mads_enabled
|
||||
return mads_enabled, acc_enabled
|
||||
|
||||
def get_sp_pedal_disengage(self, cs_out):
|
||||
accel_pedal = cs_out.gasPressed and not self.CS.out.gasPressed and self.disengage_on_accelerator
|
||||
@@ -586,22 +585,24 @@ class CarInterfaceBase(ABC):
|
||||
regen = cs_out.regenBraking and (not self.CS.out.regenBraking or not cs_out.standstill)
|
||||
return accel_pedal or brake or regen
|
||||
|
||||
def get_sp_cruise_main_state(self, cs_out):
|
||||
if not self.CS.control_initialized:
|
||||
return False
|
||||
def get_sp_cruise_main_state(self, cs_out, CS):
|
||||
if not CS.control_initialized:
|
||||
mads_enabled = False
|
||||
elif not self.CS.params_list.mads_main_toggle:
|
||||
return False
|
||||
mads_enabled = False
|
||||
else:
|
||||
return cs_out.cruiseState.available
|
||||
mads_enabled = cs_out.cruiseState.available
|
||||
|
||||
def get_sp_started_mads(self, cs_out, mads_enabled):
|
||||
if not cs_out.cruiseState.available and self.CS.out.cruiseState.available:
|
||||
return mads_enabled
|
||||
|
||||
def get_sp_started_mads(self, cs_out, CS):
|
||||
if not cs_out.cruiseState.available and CS.out.cruiseState.available:
|
||||
self.madsEnabledInit = False
|
||||
self.madsEnabledInitPrev = False
|
||||
return False
|
||||
if not self.CS.params_list.mads_main_toggle or self.prev_acc_mads_combo:
|
||||
return mads_enabled
|
||||
if not self.madsEnabledInit and self.CS.madsEnabled:
|
||||
return CS.madsEnabled
|
||||
if not self.madsEnabledInit and CS.madsEnabled:
|
||||
self.madsEnabledInit = True
|
||||
self.last_mads_init = time.monotonic()
|
||||
if cs_out.gearShifter not in FORWARD_GEARS:
|
||||
@@ -612,16 +613,19 @@ class CarInterfaceBase(ABC):
|
||||
self.madsEnabledInitPrev = True
|
||||
return cs_out.cruiseState.available
|
||||
else:
|
||||
return mads_enabled
|
||||
return CS.madsEnabled
|
||||
|
||||
def get_sp_common_state(self, cs_out, gear_allowed=True):
|
||||
cs_out.cruiseState.enabled = self.CS.accEnabled if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed 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 self.CS.out.cruiseState.enabled:
|
||||
self.CS.madsEnabled = True
|
||||
elif not cs_out.cruiseState.enabled and self.CS.out.cruiseState.enabled:
|
||||
self.CS.madsEnabled = False
|
||||
if cs_out.cruiseState.enabled and not CS.out.cruiseState.enabled:
|
||||
CS.madsEnabled = True
|
||||
elif not cs_out.cruiseState.enabled and CS.out.cruiseState.enabled:
|
||||
CS.madsEnabled = False
|
||||
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
self.toggle_exp_mode(gap_button)
|
||||
|
||||
lane_change_speed_min = get_min_lateral_speed(self.CS.params_list.pause_lateral_speed, self.CS.params_list.is_metric)
|
||||
|
||||
@@ -633,24 +637,37 @@ class CarInterfaceBase(ABC):
|
||||
|
||||
cs_out.latActive = gear_allowed
|
||||
|
||||
if not self.CS.control_initialized:
|
||||
self.CS.control_initialized = True
|
||||
if not CS.control_initialized:
|
||||
CS.control_initialized = True
|
||||
|
||||
# Disable on rising edge of gas or brake. Also disable on brake when speed > 0.
|
||||
if (cs_out.gasPressed and not self.CS.out.gasPressed and self.disengage_on_accelerator) or \
|
||||
(cs_out.brakePressed and (not self.CS.out.brakePressed or not cs_out.standstill)) or \
|
||||
(cs_out.regenBraking and (not self.CS.out.regenBraking or not cs_out.standstill)):
|
||||
if self.CS.madsEnabled:
|
||||
self.CS.disengageByBrake = True
|
||||
if CS.madsEnabled:
|
||||
CS.disengageByBrake = True
|
||||
|
||||
cs_out.madsEnabled = self.CS.madsEnabled
|
||||
cs_out.accEnabled = self.CS.accEnabled
|
||||
cs_out.disengageByBrake = self.CS.disengageByBrake
|
||||
cs_out.madsEnabled = CS.madsEnabled
|
||||
cs_out.accEnabled = CS.accEnabled
|
||||
cs_out.disengageByBrake = CS.disengageByBrake
|
||||
cs_out.brakeLightsDEPRECATED |= cs_out.brakePressed or cs_out.brakeHoldActive or cs_out.parkingBrake or cs_out.regenBraking
|
||||
|
||||
return cs_out
|
||||
return cs_out, CS
|
||||
|
||||
def create_sp_events(self, cs_out, events, main_enabled=False, allow_enable=True, enable_pressed=False,
|
||||
# TODO: SP: use upstream's buttonEvents counter checks from controlsd
|
||||
def toggle_exp_mode(self, gap_pressed):
|
||||
if gap_pressed:
|
||||
if not self.experimental_mode_hold:
|
||||
self.gap_button_counter += 1
|
||||
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.CS.params_list.experimental_mode)
|
||||
else:
|
||||
self.gap_button_counter = 0
|
||||
self.experimental_mode_hold = False
|
||||
|
||||
def create_sp_events(self, CS, cs_out, events, main_enabled=False, allow_enable=True, enable_pressed=False,
|
||||
enable_from_brake=False, enable_pressed_long=False,
|
||||
enable_buttons=(ButtonType.accelCruise, ButtonType.decelCruise)):
|
||||
|
||||
@@ -658,7 +675,7 @@ class CarInterfaceBase(ABC):
|
||||
if cs_out.disengageByBrake and cs_out.madsEnabled:
|
||||
enable_pressed = True
|
||||
enable_from_brake = True
|
||||
self.CS.disengageByBrake = False
|
||||
CS.disengageByBrake = False
|
||||
cs_out.disengageByBrake = False
|
||||
|
||||
for b in cs_out.buttonEvents:
|
||||
@@ -687,11 +704,11 @@ class CarInterfaceBase(ABC):
|
||||
if self.CP.pcmCruise:
|
||||
# do disable on button down
|
||||
if main_enabled:
|
||||
if any(self.CS.main_buttons) and not cs_out.cruiseState.enabled:
|
||||
if any(CS.main_buttons) and not cs_out.cruiseState.enabled:
|
||||
if not cs_out.madsEnabled:
|
||||
events.add(EventName.buttonCancel)
|
||||
# do enable on both accel and decel buttons
|
||||
if cs_out.cruiseState.enabled and not self.CS.out.cruiseState.enabled and allow_enable:
|
||||
if cs_out.cruiseState.enabled and not CS.out.cruiseState.enabled and allow_enable:
|
||||
enable_pressed = True
|
||||
enable_pressed_long = True
|
||||
elif not cs_out.cruiseState.enabled:
|
||||
@@ -711,19 +728,8 @@ class CarInterfaceBase(ABC):
|
||||
|
||||
return events, cs_out
|
||||
|
||||
def update_custom_stock_long(self):
|
||||
customStockLong = car.CarState.CustomStockLong.new_message()
|
||||
customStockLong.cruiseButton = 0 if self.CC.cruise_button is None else int(self.CC.cruise_button)
|
||||
customStockLong.finalSpeedKph = float(self.CC.final_speed_kph)
|
||||
customStockLong.targetSpeed = float(self.CC.target_speed)
|
||||
customStockLong.vSetDis = float(self.CC.v_set_dis)
|
||||
customStockLong.speedDiff = float(self.CC.speed_diff)
|
||||
customStockLong.buttonType = int(self.CC.button_type)
|
||||
return customStockLong
|
||||
|
||||
class RadarInterfaceBase(ABC):
|
||||
def __init__(self, CP):
|
||||
self.CP = CP
|
||||
self.rcp = None
|
||||
self.pts = {}
|
||||
self.delay = 0
|
||||
@@ -824,6 +830,16 @@ class CarStateBase(ABC):
|
||||
|
||||
return bool(left_blinker_stalk or self.left_blinker_cnt > 0), bool(right_blinker_stalk or self.right_blinker_cnt > 0)
|
||||
|
||||
def update_custom_stock_long(self, cruise_button, final_speed_kph, target_speed, v_set_dis, speed_diff, button_type):
|
||||
customStockLong = car.CarState.CustomStockLong.new_message()
|
||||
customStockLong.cruiseButton = 0 if cruise_button is None else cruise_button
|
||||
customStockLong.finalSpeedKph = final_speed_kph
|
||||
customStockLong.targetSpeed = target_speed
|
||||
customStockLong.vSetDis = v_set_dis
|
||||
customStockLong.speedDiff = speed_diff
|
||||
customStockLong.buttonType = button_type
|
||||
return customStockLong
|
||||
|
||||
@staticmethod
|
||||
def parse_gear_shifter(gear: str | None) -> car.CarState.GearShifter:
|
||||
if gear is None:
|
||||
@@ -851,17 +867,12 @@ class CarStateBase(ABC):
|
||||
return None
|
||||
|
||||
|
||||
SendCan = tuple[int, int, bytes, int]
|
||||
|
||||
|
||||
class CarControllerBase(ABC):
|
||||
def __init__(self, dbc_name: str, CP, VM):
|
||||
self.CP = CP
|
||||
self.frame = 0
|
||||
|
||||
self.cruise_button = 0
|
||||
self.final_speed_kph = 0.0
|
||||
self.target_speed = 0.0
|
||||
self.v_set_dis = 0.0
|
||||
self.speed_diff = 0.0
|
||||
self.button_type = 0
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def update(self, CC: car.CarControl.Actuators, CS: car.CarState, now_nanos: int) -> tuple[car.CarControl.Actuators, list[SendCan]]:
|
||||
|
||||
@@ -27,7 +27,7 @@ class IsoTpParallelQuery:
|
||||
assert tx_addr not in FUNCTIONAL_ADDRS, f"Functional address should be defined in functional_addrs: {hex(tx_addr)}"
|
||||
|
||||
self.msg_addrs = {tx_addr: get_rx_addr_for_tx_addr(tx_addr[0], rx_offset=response_offset) for tx_addr in real_addrs}
|
||||
self.msg_buffer: dict[int, list[tuple[int, bytes, int]]] = defaultdict(list)
|
||||
self.msg_buffer: dict[int, list[tuple[int, int, bytes, int]]] = defaultdict(list)
|
||||
|
||||
def rx(self):
|
||||
"""Drain can socket and sort messages into buffers based on address"""
|
||||
@@ -36,11 +36,11 @@ class IsoTpParallelQuery:
|
||||
for packet in can_packets:
|
||||
for msg in packet.can:
|
||||
if msg.src == self.bus and msg.address in self.msg_addrs.values():
|
||||
self.msg_buffer[msg.address].append((msg.address, msg.dat, msg.src))
|
||||
self.msg_buffer[msg.address].append((msg.address, msg.busTime, msg.dat, msg.src))
|
||||
|
||||
def _can_tx(self, tx_addr, dat, bus):
|
||||
"""Helper function to send single message"""
|
||||
msg = [tx_addr, dat, bus]
|
||||
msg = [tx_addr, 0, dat, bus]
|
||||
self.sendcan.send(can_list_to_can_capnp([msg], msgtype='sendcan'))
|
||||
|
||||
def _can_rx(self, addr, sub_addr=None):
|
||||
@@ -53,7 +53,7 @@ class IsoTpParallelQuery:
|
||||
# Filter based on subadress
|
||||
msgs = []
|
||||
for m in self.msg_buffer[addr]:
|
||||
first_byte = m[1][0]
|
||||
first_byte = m[2][0]
|
||||
if first_byte == sub_addr:
|
||||
msgs.append(m)
|
||||
else:
|
||||
|
||||
@@ -16,10 +16,11 @@ ButtonType = car.CarState.ButtonEvent.Type
|
||||
|
||||
class CarController(CarControllerBase):
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
super().__init__(dbc_name, CP, VM)
|
||||
self.CP = CP
|
||||
self.apply_steer_last = 0
|
||||
self.packer = CANPacker(dbc_name)
|
||||
self.brake_counter = 0
|
||||
self.frame = 0
|
||||
|
||||
self.sm = messaging.SubMaster(['longitudinalPlanSP'])
|
||||
self.param_s = Params()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user