commit 290159713249adbc4124cac364db24b4181a47a2 Author: FrogAi <91348155+FrogAi@users.noreply.github.com> Date: Tue Feb 27 16:34:45 2024 -0700 openpilot v0.9.6 release date: 2024-02-21T23:02:42 master commit: 0b4d08fab8e35a264bc7383e878538f8083c33e5 diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..47eb6c2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,47 @@ +name: Bug report +description: For issues with running openpilot on your comma device +labels: ["bug"] +body: + + - type: markdown + attributes: + value: > + Before creating a **bug report**, please check the following: + * If the issue likely only affects your car model or make, go back and open a **car bug report** instead. + * If the issue is related to the driving or driver monitoring models, you should open a [discussion](https://github.com/commaai/openpilot/discussions/categories/model-feedback) instead. + * Ensure you're running the latest openpilot release. + * Ensure you're using officially supported hardware. Issues running on PCs have a different issue template. + * Ensure there isn't an existing issue for your bug. If there is, leave a comment on the existing issue. + * Ensure you're running stock openpilot. We cannot look into bug reports from forks. + + If you're unsure whether you've hit a bug, check out the #installation-help channel in the [community Discord server](https://discord.comma.ai). + + - type: textarea + attributes: + label: Describe the bug + description: Also include a description of how to reproduce the bug + validations: + required: true + + - type: input + id: route + attributes: + label: Provide a route where the issue occurs + description: Ensure the route is fully uploaded at https://useradmin.comma.ai. We cannot look into issues without routes, or at least a Dongle ID. + placeholder: 77611a1fac303767|2020-05-11--16-37-07 + validations: + required: true + + - type: input + id: version + attributes: + label: openpilot version + description: If you're not on release, provide the commit hash + placeholder: 0.8.10 + validations: + required: true + + - type: textarea + attributes: + label: Additional info + diff --git a/.github/ISSUE_TEMPLATE/car_bug_report.yml b/.github/ISSUE_TEMPLATE/car_bug_report.yml new file mode 100644 index 0000000..7f368f1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/car_bug_report.yml @@ -0,0 +1,53 @@ +name: Car bug report +description: For issues with a particular car make or model +labels: ["car", "bug"] +body: + + - type: markdown + attributes: + value: > + Before creating a **bug report**, please check the following: + * Ensure you're running the latest openpilot release. + * Ensure you're using officially supported hardware. Issues running on PCs have a different issue template. + * Ensure there isn't an existing issue for your bug. If there is, leave a comment on the existing issue. + * Ensure you're running stock openpilot. We cannot look into bug reports from forks. + + If you're unsure whether you've hit a bug, check out the #installation-help channel in the [community Discord server](https://discord.comma.ai). + + - type: textarea + attributes: + label: Describe the bug + description: Also include a description of how to reproduce the bug + validations: + required: true + + - type: input + id: car + attributes: + label: Which car does this affect? + placeholder: Toyota Prius 2017 + validations: + required: true + + - type: input + id: route + attributes: + label: Provide a route where the issue occurs + description: Ensure the route is fully uploaded at https://useradmin.comma.ai + placeholder: 77611a1fac303767|2020-05-11--16-37-07 + validations: + required: true + + - type: input + id: version + attributes: + label: openpilot version + description: If you're not on release, provide the commit hash + placeholder: 0.8.10 + validations: + required: true + + - type: textarea + attributes: + label: Additional info + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..45a8af0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +blank_issues_enabled: false +contact_links: + - name: Report model bugs + url: https://github.com/commaai/openpilot/discussions/categories/model-feedback + about: Provide feedback for the driving or driver monitoring models + - name: Discussions + url: https://github.com/commaai/openpilot/discussions + about: For questions and general discussion about openpilot + - name: Community Wiki + url: https://github.com/commaai/openpilot/wiki + about: Check out our community wiki + - name: Community Discord + url: https://discord.comma.ai + about: Check out our community discord diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md new file mode 100644 index 0000000..330b9b1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -0,0 +1,8 @@ +--- +name: Enhancement +about: For openpilot enhancement suggestions +title: '' +labels: 'enhancement' +assignees: '' +--- + diff --git a/.github/ISSUE_TEMPLATE/pc_bug_report.yml b/.github/ISSUE_TEMPLATE/pc_bug_report.yml new file mode 100644 index 0000000..db3eb22 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/pc_bug_report.yml @@ -0,0 +1,42 @@ +name: PC bug report +description: For issues with running openpilot on PC +labels: ["PC"] +body: + + - type: markdown + attributes: + value: > + Before creating a **bug report**, please check the following: + * Ensure you're running the latest openpilot release. + * Ensure there isn't an existing issue for your bug. If there is, leave a comment on the existing issue. + * Ensure you're running stock openpilot. We cannot look into bug reports from forks. + + If you're unsure whether you've hit a bug, check out the #installation-help channel in the [community Discord server](https://discord.comma.ai). + + - type: textarea + attributes: + label: Describe the bug + description: Also include a description of how to reproduce the bug + validations: + required: true + + - type: input + id: os-version + attributes: + label: OS Version + placeholder: Ubuntu 20.04 + validations: + required: true + + - type: input + id: version + attributes: + label: openpilot version or commit + placeholder: bd36f2ec8d3559909678eff2690c10a520938367 + validations: + required: false + + - type: textarea + attributes: + label: Additional info + diff --git a/.github/PULL_REQUEST_TEMPLATE/bugfix.md b/.github/PULL_REQUEST_TEMPLATE/bugfix.md new file mode 100644 index 0000000..e28661d --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/bugfix.md @@ -0,0 +1,15 @@ +--- +name: Bug fix +about: For openpilot bug fixes +title: '' +labels: 'bugfix' +assignees: '' +--- + +**Description** + + + +**Verification** + + diff --git a/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md b/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md new file mode 100644 index 0000000..76c8634 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md @@ -0,0 +1,19 @@ +--- +name: Car Bug fix +about: For vehicle/brand specific bug fixes +title: '' +labels: 'car bug fix' +assignees: '' +--- + +**Description** + + + +**Verification** + + + +**Route** + +Route: [a route with the bug fix] diff --git a/.github/PULL_REQUEST_TEMPLATE/car_port.md b/.github/PULL_REQUEST_TEMPLATE/car_port.md new file mode 100644 index 0000000..690c24c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/car_port.md @@ -0,0 +1,15 @@ +--- +name: Car port +about: For new car ports +title: '' +labels: 'car port' +assignees: '' +--- + +**Checklist** + +- [ ] added entry to CarInfo in selfdrive/car/*/values.py and ran `selfdrive/car/docs.py` to generate new docs +- [ ] test route added to [routes.py](https://github.com/commaai/openpilot/blob/master/selfdrive/car/tests/routes.py) +- [ ] route with openpilot: +- [ ] route with stock system: +- [ ] car harness used (if comma doesn't sell it, put N/A): diff --git a/.github/PULL_REQUEST_TEMPLATE/fingerprint.md b/.github/PULL_REQUEST_TEMPLATE/fingerprint.md new file mode 100644 index 0000000..b94f7dc --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/fingerprint.md @@ -0,0 +1,13 @@ +--- +name: Fingerprint +about: For adding fingerprints to existing cars +title: '' +labels: 'fingerprint' +assignees: '' +--- + +**Car** +Which car (make, model, year) this fingerprint is for + +**Route** +A route with the fingerprint \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE/refactor.md b/.github/PULL_REQUEST_TEMPLATE/refactor.md new file mode 100644 index 0000000..1ee21c1 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/refactor.md @@ -0,0 +1,15 @@ +--- +name: Refactor +about: For code refactors +title: '' +labels: 'refactor' +assignees: '' +--- + +**Description** + + + +**Verification** + + diff --git a/.github/PULL_REQUEST_TEMPLATE/tuning.md b/.github/PULL_REQUEST_TEMPLATE/tuning.md new file mode 100644 index 0000000..4397e5a --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/tuning.md @@ -0,0 +1,31 @@ +--- +name: Tuning +about: For openpilot tuning changes +title: '' +labels: 'tuning' +assignees: '' +--- + +**Description** + + + +**Verification** + + \ No newline at end of file diff --git a/.github/build.py b/.github/build.py new file mode 100644 index 0000000..e141ea0 --- /dev/null +++ b/.github/build.py @@ -0,0 +1,30 @@ +import pathlib + +GITHUB_FOLDER = pathlib.Path(__file__).parent + +PULL_REQUEST_TEMPLATES = (GITHUB_FOLDER / "PULL_REQUEST_TEMPLATE") + +order = ["fingerprint", "car_bugfix", "bugfix", "car_port", "refactor"] + +def create_pull_request_template(): + with open(GITHUB_FOLDER / "pull_request_template.md", "w") as f: + f.write("\n\n") + + for t in order: + template = PULL_REQUEST_TEMPLATES / f"{t}.md" + text = template.read_text() + + # Remove metadata for GitHub + start = text.find("---") + end = text.find("---", start+1) + text = text[end + 4:] + + # Remove comments + text = text.replace("", "") + + f.write(f"\n\n") + +create_pull_request_template() diff --git a/.github/labeler.yaml b/.github/labeler.yaml new file mode 100644 index 0000000..47d0d48 --- /dev/null +++ b/.github/labeler.yaml @@ -0,0 +1,79 @@ +CI / testing: + - changed-files: + - any-glob-to-all-files: "{.github/**,**/test_*,Jenkinsfile}" + +car: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/**' + +body: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/body/*' + +chrysler: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/chrysler/*' + +ford: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/ford/*' + +gm: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/gm/*' + +honda: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/honda/*' + +hyundai: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/hyundai/*' + +mazda: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/mazda/*' + +nissan: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/nissan/*' + +subaru: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/subaru/*' + +tesla: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/telsa/*' + +toyota: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/toyota/*' + +volkswagen: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/volkswagen/*' + +fingerprint: + - changed-files: + - any-glob-to-all-files: 'selfdrive/car/*/fingerprints.py' + +simulation: + - changed-files: + - any-glob-to-all-files: 'tools/sim/**' + +ui: + - changed-files: + - any-glob-to-all-files: 'selfdrive/ui/**' + +tools: + - changed-files: + - any-glob-to-all-files: 'tools/**' + +multilanguage: + - changed-files: + - any-glob-to-all-files: 'selfdrive/ui/translations/**' + +research: + - changed-files: + - any-glob-to-all-files: "{selfdrive/modeld/models/**,selfdrive/test/process_replay/model_replay_ref_commit}" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..3e3f42d --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,68 @@ + + + + + + + + + + + + diff --git a/.github/workflows/auto-cache/action.yaml b/.github/workflows/auto-cache/action.yaml new file mode 100644 index 0000000..173803f --- /dev/null +++ b/.github/workflows/auto-cache/action.yaml @@ -0,0 +1,49 @@ +name: 'automatically cache based on current runner' + +inputs: + path: + description: 'path to cache' + required: true + key: + description: 'key' + required: true + restore-keys: + description: 'restore-keys' + required: true + save: + description: 'whether to save the cache' + default: 'false' + required: false + +runs: + using: "composite" + steps: + - name: setup namespace cache + if: ${{ contains(runner.name, 'nsc') }} + uses: namespacelabs/nscloud-cache-action@v1 + with: + path: ${{ inputs.path }} + + - name: setup github cache + if: ${{ !contains(runner.name, 'nsc') && inputs.save != 'false' }} + uses: 'actions/cache@v3' + with: + path: ${{ inputs.path }} + key: ${{ inputs.key }} + restore-keys: ${{ inputs.restore-keys }} + + - name: setup github cache + if: ${{ !contains(runner.name, 'nsc') && inputs.save == 'false' }} + uses: 'actions/cache/restore@v3' + with: + path: ${{ inputs.path }} + key: ${{ inputs.key }} + restore-keys: ${{ inputs.restore-keys }} + + # make the directory manually in case we didn't get a hit, so it doesn't fail on future steps + - id: scons-cache-setup + shell: bash + run: | + mkdir -p ${{ inputs.path }} + sudo chmod -R 777 ${{ inputs.path }} + sudo chown -R $USER ${{ inputs.path }} \ No newline at end of file diff --git a/.github/workflows/auto_pr_review.yaml b/.github/workflows/auto_pr_review.yaml new file mode 100644 index 0000000..42ef4db --- /dev/null +++ b/.github/workflows/auto_pr_review.yaml @@ -0,0 +1,227 @@ +name: "PR review" +on: + pull_request_target: + types: [opened, reopened, synchronize, edited, edited] + +jobs: + labeler: + name: apply labels + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: false + - uses: actions/labeler@v5.0.0 + with: + dot: true + configuration-path: .github/labeler.yaml + + pr_branch_check: + name: check branch + runs-on: ubuntu-latest + if: github.repository == 'commaai/openpilot' + steps: + - uses: Vankka/pr-target-branch-action@69ab6dd5c221de3548b3b6c4d102c1f4913d3baa + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + target: /^(?!master$).*/ + exclude: /commaai:.*/ + change-to: ${{ github.base_ref }} + already-exists-action: close_this + already-exists-comment: "Your PR should be made against the `master` branch" + + comment: + runs-on: ubuntu-latest + steps: + - name: comment + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 + if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot' + with: + message: | + + Thanks for contributing to openpilot! In order for us to review your PR as quickly as possible, check the following: + * Convert your PR to a draft unless it's ready to review + * Read the [contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md) + * Before marking as "ready for review", ensure: + * the goal is clearly stated in the description + * all the tests are passing + * the change is [something we merge](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md#what-gets-merged) + * include a route or your device' dongle ID if relevant + comment_tag: run_id + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + check-pr-template: + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + pull-requests: write + actions: read + if: false && github.event.pull_request.head.repo.full_name != 'commaai/openpilot' + steps: + - uses: actions/github-script@v7 + with: + script: | + // Comment to add to the PR if no template has been used + const NO_TEMPLATE_MESSAGE = + "It looks like you didn't use one of the Pull Request templates. Please check [the contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md). \ + Also make sure that you didn't modify any of the checkboxes or headings within the template."; + // body data for future requests + const body_data = { + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + }; + + // Utility function to extract all headings + const extractHeadings = (markdown) => { + const headingRegex = /^(#{1,6})\s+(.+)$/gm; + const boldTextRegex = /^(?:\*\*|__)(.+?)(?:\*\*|__)\s*$/gm; + const headings = []; + let headingMatch; + while ((headingMatch = headingRegex.exec(markdown))) { + headings.push(headingMatch[2].trim()); + } + let boldMatch; + while ((boldMatch = boldTextRegex.exec(markdown))) { + headings.push(boldMatch[1].trim()); + } + return headings; + }; + + // Utility function to extract all check box descriptions + const extractCheckBoxTexts = (markdown) => { + const checkboxRegex = /^\s*-\s*\[( |x)\]\s+(.+)$/gm; + const checkboxes = []; + let match; + while ((match = checkboxRegex.exec(markdown))) { + checkboxes.push(match[2].trim()); + } + return checkboxes; + }; + + // Utility function to check if a list is a subset of another list + isSubset = (subset, superset) => { + return subset.every((item) => superset.includes(item)); + }; + + // Utility function to check if a list of checkboxes is a subset of another list of checkboxes + isCheckboxSubset = (templateCheckBoxTexts, prTextCheckBoxTexts) => { + // Check if each template checkbox text is a substring of at least one PR checkbox text + // (user should be allowed to add additional text) + return templateCheckBoxTexts.every((item) => prTextCheckBoxTexts.some((element) => element.includes(item))) + } + + // Get filenames of all currently checked-in PR templates + const template_contents = await github.rest.repos.getContent({ + owner: context.repo.owner, + repo: context.repo.repo, + path: ".github/PULL_REQUEST_TEMPLATE", + }); + var template_filenames = []; + for (const content of template_contents.data) { + template_filenames.push(content.path); + } + console.debug("Received template filenames: " + template_filenames); + // Retrieve templates + var templates = []; + for (const template_filename of template_filenames) { + const template_response = await github.rest.repos.getContent({ + owner: context.repo.owner, + repo: context.repo.repo, + path: template_filename, + }); + // Convert Base64 content back + const decoded_template = atob(template_response.data.content); + const headings = extractHeadings(decoded_template); + const checkboxes = extractCheckBoxTexts(decoded_template); + if (!headings.length && !checkboxes.length) { + console.warn( + "Invalid template! Contains neither headings nor checkboxes, ignoring it: \n" + + decoded_template + ); + } else { + templates.push({ headings: headings, checkboxes: checkboxes }); + } + } + // Retrieve the PR Body + const pull_request = await github.rest.issues.get({ + ...body_data, + }); + const pull_request_text = pull_request.data.body; + console.debug("Received Pull Request body: \n" + pull_request_text); + + /* Check if the PR Body matches one of the templates + A template is defined by all headings and checkboxes it contains + We extract all Headings and Checkboxes from the PR text and check if any of the templates is a subset of that + */ + const pr_headings = extractHeadings(pull_request_text); + const pr_checkboxes = extractCheckBoxTexts(pull_request_text); + console.debug("Found Headings in PR body:\n" + pr_headings); + console.debug("Found Checkboxes in PR body:\n" + pr_checkboxes); + var template_found = false; + // Iterate over each template to check if it applies + for (const template of templates) { + console.log( + "Checking for headings: [" + + template.headings + + "] and checkboxes: [" + + template.checkboxes + "]" + ); + if ( + isCheckboxSubset(template.checkboxes, pr_checkboxes) && + isSubset(template.headings, pr_headings) + ) { + console.debug("Found matching template!"); + template_found = true; + } + } + + // List comments from previous runs + var existing_comments = []; + const comments = await github.rest.issues.listComments({ + ...body_data, + }); + for (const comment of comments.data) { + if (comment.body === NO_TEMPLATE_MESSAGE) { + existing_comments.push(comment); + } + } + + // Add a comment to the PR that it is not using a the template (but only if this comment does not exist already) + if (!template_found) { + var comment_already_sent = false; + + // Add an 'in-bot-review' label since this PR doesn't have the template + github.rest.issues.addLabels({ + ...body_data, + labels: ["in-bot-review"], + }); + + if (existing_comments.length < 1) { + github.rest.issues.createComment({ + ...body_data, + body: NO_TEMPLATE_MESSAGE, + }); + } + } else { + // If template has been found, delete any old comment about missing template + for (const existing_comment of existing_comments) { + github.rest.issues.deleteComment({ + ...body_data, + comment_id: existing_comment.id, + }); + } + // Remove the 'in-bot-review' label after the review is done and the PR has passed + github.rest.issues.removeLabel({ + ...body_data, + name: "in-bot-review", + }).catch((error) => { + console.log("Label 'in-bot-review' not found, ignoring"); + }); + } + diff --git a/.github/workflows/badges.yaml b/.github/workflows/badges.yaml new file mode 100644 index 0000000..2f1a7d6 --- /dev/null +++ b/.github/workflows/badges.yaml @@ -0,0 +1,37 @@ +name: badges +on: + schedule: + - cron: '0 * * * *' + workflow_dispatch: + +env: + BASE_IMAGE: openpilot-base + DOCKER_REGISTRY: ghcr.io/commaai + RUN: docker run --shm-size 1G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $DOCKER_REGISTRY/$BASE_IMAGE:latest /bin/bash -c + +jobs: + badges: + name: create badges + runs-on: ubuntu-20.04 + if: github.repository == 'commaai/openpilot' + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + - name: Push badges + run: | + ${{ env.RUN }} "scons -j$(nproc) && python selfdrive/ui/translations/create_badges.py" + + rm .gitattributes + + git checkout --orphan badges + git rm -rf --cached . + git config user.email "badge-researcher@comma.ai" + git config user.name "Badge Researcher" + + git add translation_badge.svg + git commit -m "Add/Update badges" + git push -f origin HEAD diff --git a/.github/workflows/compile-openpilot/action.yaml b/.github/workflows/compile-openpilot/action.yaml new file mode 100644 index 0000000..2945b67 --- /dev/null +++ b/.github/workflows/compile-openpilot/action.yaml @@ -0,0 +1,21 @@ +name: 'compile openpilot' + +runs: + using: "composite" + steps: + - shell: bash + name: Build openpilot with all flags + run: | + ${{ env.RUN }} "scons -j$(nproc)" + ${{ env.RUN }} "release/check-dirty.sh" + - shell: bash + name: Cleanup scons cache and rebuild + run: | + ${{ env.RUN }} "rm -rf /tmp/scons_cache/* && \ + scons -j$(nproc) --cache-populate" + - name: Save scons cache + uses: actions/cache/save@v3 + if: github.ref == 'refs/heads/master' + with: + path: .ci_cache/scons_cache + key: scons-${{ runner.arch }}-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }} diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml new file mode 100644 index 0000000..c555eaf --- /dev/null +++ b/.github/workflows/docs.yaml @@ -0,0 +1,64 @@ +name: docs + +on: + push: + branches: + - master + pull_request: + +concurrency: + group: ${{ 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-20.04 + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + - name: Build openpilot + run: | + ${{ env.RUN }} "scons -j$(nproc)" + - name: Build docs + run: | + ${{ env.RUN }} "apt update && apt install -y doxygen && cd docs && make -j$(nproc) html" + + - uses: actions/checkout@v4 + if: github.ref == 'refs/heads/master' && github.repository == 'commaai/openpilot' + with: + path: openpilot-docs + ssh-key: ${{ secrets.OPENPILOT_DOCS_KEY }} + repository: commaai/openpilot-docs + - name: Push + if: github.ref == 'refs/heads/master' && github.repository == 'commaai/openpilot' + run: | + set -x + + source release/identity.sh + + cd openpilot-docs + + git checkout --orphan tmp + git rm -rf . + + 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 + git push -f origin tmp:gh-pages diff --git a/.github/workflows/prebuilt.yaml b/.github/workflows/prebuilt.yaml new file mode 100644 index 0000000..990be73 --- /dev/null +++ b/.github/workflows/prebuilt.yaml @@ -0,0 +1,39 @@ +name: prebuilt +on: + schedule: + - cron: '0 * * * *' + workflow_dispatch: + +env: + DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }} + BUILD: selfdrive/test/docker_build.sh prebuilt + +jobs: + build_prebuilt: + name: build prebuilt + runs-on: ubuntu-20.04 + if: github.repository == 'commaai/openpilot' + env: + PUSH_IMAGE: true + permissions: + checks: read + contents: read + packages: write + steps: + - name: Wait for green check mark + if: ${{ github.event_name != 'workflow_dispatch' }} + uses: lewagon/wait-on-check-action@595dabb3acf442d47e29c9ec9ba44db0c6bdd18f + with: + ref: master + wait-interval: 30 + running-workflow-name: 'build prebuilt' + repo-token: ${{ secrets.GITHUB_TOKEN }} + check-regexp: ^((?!.*(build master-ci).*).)*$ + - uses: actions/checkout@v4 + with: + submodules: true + - run: git lfs pull + - name: Build and Push docker image + run: | + $DOCKER_LOGIN + eval "$BUILD" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..3e3fe46 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,54 @@ +name: release +on: + schedule: + - cron: '0 10 * * *' + workflow_dispatch: + +jobs: + build_masterci: + name: build master-ci + env: + TARGET_DIR: /tmp/openpilot + ImageOS: ubuntu20 + container: + image: ghcr.io/commaai/openpilot-base:latest + runs-on: ubuntu-20.04 + if: github.repository == 'commaai/openpilot' + permissions: + checks: read + contents: write + steps: + - name: Install wait-on-check-action dependencies + run: | + sudo apt-get update + sudo apt-get install -y libyaml-dev + - name: Wait for green check mark + if: ${{ github.event_name != 'workflow_dispatch' }} + uses: lewagon/wait-on-check-action@595dabb3acf442d47e29c9ec9ba44db0c6bdd18f + with: + ref: master + wait-interval: 30 + running-workflow-name: 'build master-ci' + repo-token: ${{ secrets.GITHUB_TOKEN }} + check-regexp: ^((?!.*(build prebuilt).*).)*$ + - uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + - name: Pull LFS + run: | + git config --global --add safe.directory '*' + git lfs pull + - name: Build master-ci + run: | + release/build_devel.sh + - name: Run tests + run: | + export PYTHONPATH=$TARGET_DIR + cd $TARGET_DIR + scons -j$(nproc) + pytest -n logical selfdrive/car/tests/test_car_interfaces.py + - name: Push master-ci + run: | + unset TARGET_DIR + BRANCH=master-ci release/build_devel.sh diff --git a/.github/workflows/repo-maintenance.yaml b/.github/workflows/repo-maintenance.yaml new file mode 100644 index 0000000..445a1cf --- /dev/null +++ b/.github/workflows/repo-maintenance.yaml @@ -0,0 +1,61 @@ +name: repo maintenance + +on: + schedule: + - cron: "0 14 * * 1" # every Monday at 2am UTC (6am PST) + workflow_dispatch: + +jobs: + bump_submodules: + name: bump_submodules + runs-on: ubuntu-20.04 + container: + image: ghcr.io/commaai/openpilot-base:latest + if: github.repository == 'commaai/openpilot' + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: bump submodules + run: | + git config --global --add safe.directory '*' + git -c submodule."tinygrad".update=none submodule update --remote + git add . + - name: Create Pull Request + uses: peter-evans/create-pull-request@5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5 + with: + token: ${{ secrets.ACTIONS_CREATE_PR_PAT }} + commit-message: bump submodules + title: '[bot] Bump submodules' + branch: auto-bump-submodules + base: master + delete-branch: true + body: 'Automatic PR from repo-maintenance -> bump_submodules' + labels: bot + package_updates: + name: package_updates + runs-on: ubuntu-20.04 + container: + image: ghcr.io/commaai/openpilot-base:latest + if: github.repository == 'commaai/openpilot' + steps: + - uses: actions/checkout@v4 + - name: poetry lock + run: | + pip install poetry + poetry lock + - name: pre-commit autoupdate + run: | + git config --global --add safe.directory '*' + pre-commit autoupdate + - name: Create Pull Request + uses: peter-evans/create-pull-request@5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5 + with: + token: ${{ secrets.ACTIONS_CREATE_PR_PAT }} + 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 + body: 'Automatic PR from repo-maintenance -> package_updates' + labels: bot diff --git a/.github/workflows/selfdrive_tests.yaml b/.github/workflows/selfdrive_tests.yaml new file mode 100644 index 0000000..d1dff14 --- /dev/null +++ b/.github/workflows/selfdrive_tests.yaml @@ -0,0 +1,404 @@ +name: selfdrive + +on: + push: + branches: + - master + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }} + cancel-in-progress: true + +env: + PYTHONWARNINGS: error + BASE_IMAGE: openpilot-base + AZURE_TOKEN: ${{ secrets.AZURE_COMMADATACI_OPENPILOTCI_TOKEN }} + + DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }} + BUILD: selfdrive/test/docker_build.sh base + + RUN: docker run --shm-size 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 + +jobs: + build_release: + name: build release + runs-on: ubuntu-20.04 + env: + STRIPPED_DIR: /tmp/releasepilot + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - run: git lfs pull + - 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' + timeout-minutes: 1 + run: release/check-submodules.sh + - name: Build openpilot and run checks + timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 10 || 30) }} # allow more time when we missed the scons cache + run: | + cd $STRIPPED_DIR + ${{ env.RUN }} "python selfdrive/manager/build.py" + - name: Run tests + timeout-minutes: 3 + run: | + cd $STRIPPED_DIR + ${{ env.RUN }} "release/check-dirty.sh && \ + MAX_EXAMPLES=5 $PYTEST selfdrive/car" + - name: pre-commit + timeout-minutes: 3 + run: | + cd $GITHUB_WORKSPACE + cp .pre-commit-config.yaml $STRIPPED_DIR + cp pyproject.toml $STRIPPED_DIR + cp poetry.lock $STRIPPED_DIR + cd $STRIPPED_DIR + ${{ env.RUN }} "unset PYTHONWARNINGS && SKIP=check-added-large-files 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-20.04' }} + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + with: + docker_hub_pat: ${{ secrets.DOCKER_HUB_PAT }} + - uses: ./.github/workflows/compile-openpilot + timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 15 || 30) }} # allow more time when we missed the scons cache + + docker_push: + name: docker push + strategy: + matrix: + arch: ${{ fromJson( (github.repository == 'commaai/openpilot') && '["x86_64", "aarch64"]' || '["x86_64"]' ) }} + runs-on: ${{ (matrix.arch == 'aarch64') && 'namespace-profile-arm64-2x8' || 'ubuntu-20.04' }} + if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot' + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Setup to push to repo + run: | + echo "PUSH_IMAGE=true" >> "$GITHUB_ENV" + echo "TARGET_ARCHITECTURE=${{ matrix.arch }}" >> "$GITHUB_ENV" + $DOCKER_LOGIN + - uses: ./.github/workflows/setup-with-retry + with: + docker_hub_pat: ${{ secrets.DOCKER_HUB_PAT }} + + docker_push_multiarch: + name: docker push multiarch tag + runs-on: ubuntu-20.04 + if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot' + needs: [docker_push] + steps: + - uses: actions/checkout@v4 + with: + submodules: false + - name: Setup docker + run: | + $DOCKER_LOGIN + - name: Merge x64 and arm64 tags + run: | + export PUSH_IMAGE=true + scripts/retry.sh selfdrive/test/docker_tag_multiarch.sh base x86_64 aarch64 + + static_analysis: + name: static analysis + runs-on: ${{ ((github.repository == 'commaai/openpilot') && + ((github.event_name != 'pull_request') || + (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-20.04' }} + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-pre-commit + - uses: ./.github/workflows/setup-with-retry + - name: pre-commit + timeout-minutes: 4 + run: ${{ env.RUN }} "unset PYTHONWARNINGS && pre-commit run --all && chmod -R 777 /tmp/pre-commit" + + valgrind: + name: valgrind + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + - name: Build openpilot + run: ${{ env.RUN }} "scons -j$(nproc)" + - name: Run valgrind + timeout-minutes: 1 + run: | + ${{ env.RUN }} "python selfdrive/test/test_valgrind_replay.py" + - name: Print logs + if: always() + run: cat selfdrive/test/valgrind_logs.txt + + unit_tests: + name: unit tests + runs-on: ${{ ((github.repository == 'commaai/openpilot') && + ((github.event_name != 'pull_request') || + (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-20.04' }} + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + with: + docker_hub_pat: ${{ secrets.DOCKER_HUB_PAT }} + - name: Build openpilot + timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 10 || 30) }} # allow more time when we missed the scons cache + run: ${{ env.RUN }} "scons -j$(nproc)" + - name: Run unit tests + timeout-minutes: 15 + run: | + ${{ env.RUN }} "source selfdrive/test/setup_xvfb.sh && \ + export MAPBOX_TOKEN='pk.eyJ1Ijoiam5ld2IiLCJhIjoiY2xxNW8zZXprMGw1ZzJwbzZneHd2NHljbSJ9.gV7VPRfbXFetD-1OVF0XZg' && \ + $PYTEST --timeout 60 -m 'not slow' && \ + ./selfdrive/ui/tests/create_test_translations.sh && \ + QT_QPA_PLATFORM=offscreen ./selfdrive/ui/tests/test_translations && \ + ./selfdrive/ui/tests/test_translations.py" + - name: "Upload coverage to Codecov" + uses: codecov/codecov-action@v3 + with: + name: ${{ github.job }} + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + process_replay: + name: process replay + runs-on: ${{ ((github.repository == 'commaai/openpilot') && + ((github.event_name != 'pull_request') || + (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-20.04' }} + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + with: + docker_hub_pat: ${{ secrets.DOCKER_HUB_PAT }} + - name: Cache test routes + id: dependency-cache + uses: actions/cache@v3 + with: + path: .ci_cache/comma_download_cache + key: proc-replay-${{ hashFiles('.github/workflows/selfdrive_tests.yaml', 'selfdrive/test/process_replay/ref_commit') }} + - name: Build openpilot + run: | + ${{ env.RUN }} "scons -j$(nproc)" + - name: Run replay + timeout-minutes: 30 + run: | + ${{ env.RUN }} "coverage run selfdrive/test/process_replay/test_processes.py -j$(nproc) && \ + chmod -R 777 /tmp/comma_download_cache && \ + coverage combine && \ + coverage xml" + - name: Print diff + id: print-diff + if: always() + run: cat selfdrive/test/process_replay/diff.txt + - uses: actions/upload-artifact@v3 + if: always() + continue-on-error: true + with: + name: process_replay_diff.txt + path: selfdrive/test/process_replay/diff.txt + - name: Upload reference logs + if: ${{ failure() && steps.print-diff.outcome == 'success' && github.repository == 'commaai/openpilot' && env.AZURE_TOKEN != '' }} + run: | + ${{ env.RUN }} "unset PYTHONWARNINGS && AZURE_TOKEN='$AZURE_TOKEN' python selfdrive/test/process_replay/test_processes.py -j$(nproc) --upload-only" + - name: "Upload coverage to Codecov" + uses: codecov/codecov-action@v3 + with: + name: ${{ github.job }} + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + regen: + name: regen + runs-on: 'ubuntu-20.04' + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + - name: Cache test routes + id: dependency-cache + uses: actions/cache@v3 + with: + path: .ci_cache/comma_download_cache + key: regen-${{ hashFiles('.github/workflows/selfdrive_tests.yaml', 'selfdrive/test/process_replay/test_regen.py') }} + - name: Build base Docker image + run: eval "$BUILD" + - name: Build openpilot + run: | + ${{ env.RUN }} "scons -j$(nproc)" + - name: Run regen + timeout-minutes: 30 + run: | + ${{ env.RUN }} "ONNXCPU=1 $PYTEST selfdrive/test/process_replay/test_regen.py && \ + chmod -R 777 /tmp/comma_download_cache" + + test_modeld: + name: model tests + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + - name: Build base Docker image + run: eval "$BUILD" + - name: Build openpilot + run: | + ${{ env.RUN }} "scons -j$(nproc)" + # PYTHONWARNINGS triggers a SyntaxError in onnxruntime + - name: Run model replay with ONNX + timeout-minutes: 4 + run: | + ${{ env.RUN }} "unset PYTHONWARNINGS && \ + ONNXCPU=1 NO_NAV=1 coverage run selfdrive/test/process_replay/model_replay.py && \ + coverage combine && \ + coverage xml" + - name: Run unit tests + timeout-minutes: 4 + run: | + ${{ env.RUN }} "unset PYTHONWARNINGS && \ + $PYTEST selfdrive/modeld" + - name: "Upload coverage to Codecov" + uses: codecov/codecov-action@v3 + with: + name: ${{ github.job }} + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + test_cars: + name: cars + runs-on: ${{ ((github.repository == 'commaai/openpilot') && + ((github.event_name != 'pull_request') || + (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-20.04' }} + strategy: + fail-fast: false + matrix: + job: [0, 1, 2, 3, 4] + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + - name: Cache test routes + id: dependency-cache + uses: ./.github/workflows/auto-cache + with: + path: .ci_cache/comma_download_cache + key: car_models-${{ hashFiles('selfdrive/car/tests/test_models.py', 'selfdrive/car/tests/routes.py') }}-${{ matrix.job }} + - name: Build openpilot + run: ${{ env.RUN }} "scons -j$(nproc)" + - name: Test car models + timeout-minutes: 10 + run: | + ${{ env.RUN }} "$PYTEST selfdrive/car/tests/test_models.py && \ + chmod -R 777 /tmp/comma_download_cache" + env: + NUM_JOBS: 5 + JOB_ID: ${{ matrix.job }} + - name: "Upload coverage to Codecov" + uses: codecov/codecov-action@v3 + with: + name: ${{ github.job }}-${{ matrix.job }} + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + car_docs_diff: + name: PR comments + runs-on: ubuntu-20.04 + if: github.event_name == 'pull_request' + steps: + - uses: actions/checkout@v4 + with: + submodules: true + ref: ${{ github.event.pull_request.base.ref }} + - run: git lfs pull + - uses: ./.github/workflows/setup-with-retry + - name: Get base car info + run: | + ${{ env.RUN }} "scons -j$(nproc) && python selfdrive/debug/dump_car_info.py --path /tmp/openpilot_cache/base_car_info" + sudo chown -R $USER:$USER ${{ github.workspace }} + - uses: actions/checkout@v4 + with: + submodules: true + path: current + - run: cd current && git lfs pull + - name: Save car docs diff + id: save_diff + run: | + cd current + ${{ env.RUN }} "scons -j$(nproc)" + output=$(${{ env.RUN }} "python selfdrive/debug/print_docs_diff.py --path /tmp/openpilot_cache/base_car_info") + output="${output//$'\n'/'%0A'}" + echo "::set-output name=diff::$output" + - name: Find comment + if: ${{ env.AZURE_TOKEN != '' }} + uses: peter-evans/find-comment@1769778a0c5bd330272d749d12c036d65e70d39d + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + body-includes: This PR makes changes to + - name: Update comment + if: ${{ steps.save_diff.outputs.diff != '' && env.AZURE_TOKEN != '' }} + uses: peter-evans/create-or-update-comment@b95e16d2859ad843a14218d1028da5b2c4cbc4b4 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: "${{ steps.save_diff.outputs.diff }}" + edit-mode: replace + - name: Delete comment + if: ${{ steps.fc.outputs.comment-id != '' && steps.save_diff.outputs.diff == '' && env.AZURE_TOKEN != '' }} + uses: actions/github-script@v6 + with: + script: | + github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: ${{ steps.fc.outputs.comment-id }} + }) + + create_ui_report: + name: Create UI Report + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + - name: Build openpilot + run: ${{ env.RUN }} "scons -j$(nproc)" + - name: Create Test Report + run: > + ${{ env.RUN }} "PYTHONWARNINGS=ignore && + source selfdrive/test/setup_xvfb.sh && + export MAPBOX_TOKEN='pk.eyJ1Ijoiam5ld2IiLCJhIjoiY2xxNW8zZXprMGw1ZzJwbzZneHd2NHljbSJ9.gV7VPRfbXFetD-1OVF0XZg' && + python selfdrive/ui/tests/test_ui/run.py" + - name: Upload Test Report + uses: actions/upload-artifact@v2 + with: + name: report + path: selfdrive/ui/tests/test_ui/report \ No newline at end of file diff --git a/.github/workflows/setup-pre-commit/action.yaml b/.github/workflows/setup-pre-commit/action.yaml new file mode 100644 index 0000000..1b3e16e --- /dev/null +++ b/.github/workflows/setup-pre-commit/action.yaml @@ -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' }} diff --git a/.github/workflows/setup-with-retry/action.yaml b/.github/workflows/setup-with-retry/action.yaml new file mode 100644 index 0000000..369ac45 --- /dev/null +++ b/.github/workflows/setup-with-retry/action.yaml @@ -0,0 +1,40 @@ +name: 'openpilot env setup, with retry on failure' + +inputs: + docker_hub_pat: + description: 'Auth token for Docker Hub, required for BuildJet jobs' + required: false + default: '' + sleep_time: + description: 'Time to sleep between retries' + required: false + default: 30 + +runs: + using: "composite" + steps: + - id: setup1 + uses: ./.github/workflows/setup + continue-on-error: true + with: + docker_hub_pat: ${{ inputs.docker_hub_pat }} + is_retried: true + - if: steps.setup1.outcome == 'failure' + shell: bash + run: sleep ${{ inputs.sleep_time }} + - id: setup2 + if: steps.setup1.outcome == 'failure' + uses: ./.github/workflows/setup + continue-on-error: true + with: + docker_hub_pat: ${{ inputs.docker_hub_pat }} + is_retried: true + - if: steps.setup2.outcome == 'failure' + shell: bash + run: sleep ${{ inputs.sleep_time }} + - id: setup3 + if: steps.setup2.outcome == 'failure' + uses: ./.github/workflows/setup + with: + docker_hub_pat: ${{ inputs.docker_hub_pat }} + is_retried: true diff --git a/.github/workflows/setup/action.yaml b/.github/workflows/setup/action.yaml new file mode 100644 index 0000000..970d620 --- /dev/null +++ b/.github/workflows/setup/action.yaml @@ -0,0 +1,63 @@ +name: 'openpilot env setup' + +inputs: + docker_hub_pat: + description: 'Auth token for Docker Hub, required for BuildJet jobs' + required: true + default: '' + is_retried: + description: 'A mock param that asserts that we use the setup-with-retry instead of this action directly' + required: false + default: 'false' + +runs: + using: "composite" + steps: + # assert that this action is retried using the setup-with-retry + - shell: bash + if: ${{ inputs.is_retried == 'false' }} + run: | + echo "You should not run this action directly. Use setup-with-retry instead" + exit 1 + + # do this after checkout to ensure our custom LFS config is used to pull from GitLab + - shell: bash + run: git lfs pull + + # on BuildJet runners, must be logged into DockerHub to avoid rate limiting + # https://buildjet.com/for-github-actions/docs/guides/docker + - shell: bash + if: ${{ contains(runner.name, 'buildjet') && inputs.docker_hub_pat == '' }} + run: | + echo "Need to set the Docker Hub PAT secret as an input to this action" + exit 1 + - name: Login to Docker Hub + if: contains(runner.name, 'buildjet') + shell: bash + run: | + docker login -u adeebshihadeh -p ${{ inputs.docker_hub_pat }} + + # build cache + - id: date + shell: bash + run: echo "CACHE_COMMIT_DATE=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d-%H:%M')" >> $GITHUB_ENV + - shell: bash + run: echo "$CACHE_COMMIT_DATE" + - id: scons-cache + uses: ./.github/workflows/auto-cache + with: + path: .ci_cache/scons_cache + key: scons-${{ runner.arch }}-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }} + restore-keys: | + scons-${{ runner.arch }}-${{ env.CACHE_COMMIT_DATE }} + scons-${{ runner.arch }} + # as suggested here: https://github.com/moby/moby/issues/32816#issuecomment-910030001 + - id: normalize-file-permissions + shell: bash + name: Normalize file permissions to ensure a consistent docker build cache + run: | + find . -type f -executable -not -perm 755 -exec chmod 755 {} \; + find . -type f -not -executable -not -perm 644 -exec chmod 644 {} \; + # build our docker image + - shell: bash + run: eval ${{ env.BUILD }} \ No newline at end of file diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 0000000..2d60d2f --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,28 @@ +name: stale +on: + schedule: + - cron: '30 1 * * *' + workflow_dispatch: + +env: + DAYS_BEFORE_PR_CLOSE: 7 + DAYS_BEFORE_PR_STALE: 30 + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v8 + with: + exempt-milestones: true + + # pull request config + stale-pr-message: 'This PR has had no activity for ${{ env.DAYS_BEFORE_PR_STALE }} days. It will be automatically closed in ${{ env.DAYS_BEFORE_PR_CLOSE }} days if there is no activity.' + close-pr-message: 'This PR has been automatically closed due to inactivity. Feel free to re-open once activity resumes.' + delete-branch: ${{ github.event.pull_request.head.repo.full_name == 'commaai/openpilot' }} # only delete branches on the main repo + exempt-pr-labels: "ignore stale,needs testing,car port" # if wip or it needs testing from the community, don't mark as stale + days-before-pr-stale: ${{ env.DAYS_BEFORE_PR_STALE }} + days-before-pr-close: ${{ env.DAYS_BEFORE_PR_CLOSE }} + + # issue config + days-before-issue-stale: -1 # ignore issues for now diff --git a/.github/workflows/tools_tests.yaml b/.github/workflows/tools_tests.yaml new file mode 100644 index 0000000..a051cb1 --- /dev/null +++ b/.github/workflows/tools_tests.yaml @@ -0,0 +1,102 @@ +name: tools + +on: + push: + branches: + - master + pull_request: + +concurrency: + group: ${{ 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 + DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }} + + BUILD: selfdrive/test/docker_build.sh base + + RUN: docker run --shm-size 1G -v $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: + plotjuggler: + name: plotjuggler + runs-on: ubuntu-20.04 + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + - name: Build openpilot + timeout-minutes: 5 + run: ${{ env.RUN }} "scons -j$(nproc) cereal/ common/ --minimal" + - name: Test PlotJuggler + timeout-minutes: 2 + run: | + ${{ env.RUN }} "pytest tools/plotjuggler/" + + simulator: + name: simulator + runs-on: ubuntu-20.04 + if: github.repository == 'commaai/openpilot' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + - name: Setup to push to repo + if: github.ref == 'refs/heads/master' && github.repository == 'commaai/openpilot' + run: | + echo "PUSH_IMAGE=true" >> "$GITHUB_ENV" + $DOCKER_LOGIN + - name: Build and push sim image + run: | + selfdrive/test/docker_build.sh sim + + devcontainer: + name: devcontainer + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + - name: Use local image for testing devcontainer with latest base image + run: | + echo "USE_LOCAL_IMAGE=true" >> "$GITHUB_ENV" + - name: Setup Dev Container CLI + run: npm install -g @devcontainers/cli + - name: Build dev container image + run: devcontainer build --workspace-folder . + - name: Run dev container + run: | + mkdir -p /tmp/devcontainer_scons_cache/ + cp -r $GITHUB_WORKSPACE/.ci_cache/scons_cache/. /tmp/devcontainer_scons_cache/ + devcontainer up --workspace-folder . + - name: Test environment + run: | + devcontainer exec --workspace-folder . scons -j$(nproc) cereal/ common/ + devcontainer exec --workspace-folder . pip install pip-install-test + devcontainer exec --workspace-folder . touch /home/batman/.comma/auth.json + devcontainer exec --workspace-folder . sudo touch /root/test.txt + + notebooks: + name: notebooks + runs-on: ubuntu-20.04 + if: false && github.repository == 'commaai/openpilot' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/workflows/setup-with-retry + - name: Build openpilot + timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 10 || 30) }} # allow more time when we missed the scons cache + run: ${{ env.RUN }} "scons -j$(nproc)" + - name: Test notebooks + timeout-minutes: 3 + run: | + ${{ env.RUN }} "pip install nbmake && pytest --nbmake tools/car_porting/examples/" \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3e91531 --- /dev/null +++ b/.gitignore @@ -0,0 +1,90 @@ +venv/ +.venv/ +.ci_cache +.env +.clang-format +.DS_Store +.tags +.ipynb_checkpoints +.idea +.overlay_init +.overlay_consistent +.sconsign.dblite +.vscode* +model2.png +a.out +.hypothesis + +*.dylib +*.DSYM +*.d +*.pyc +*.pyo +.*.swp +.*.swo +.*.un~ +*.tmp +*.o +*.o-* +*.os +*.os-* +*.so +*.a +*.clb +*.class +*.pyxbldc +*.vcd +*.qm +config.json +clcache +compile_commands.json +compare_runtime*.html + +persist +board/obj/ +selfdrive/boardd/boardd +selfdrive/logcatd/logcatd +selfdrive/mapd/default_speeds_by_region.json +system/proclogd/proclogd +selfdrive/ui/translations/alerts_generated.h +selfdrive/ui/translations/tmp +selfdrive/test/longitudinal_maneuvers/out +selfdrive/car/tests/cars_dump +system/camerad/camerad +system/camerad/test/ae_gray_test +selfdrive/modeld/_modeld +selfdrive/modeld/_navmodeld +selfdrive/modeld/_dmonitoringmodeld +/src/ + +one +notebooks +xx +yy +hyperthneed +panda_jungle +provisioning + +.coverage* +coverage.xml +htmlcov +pandaextra + +.mypy_cache/ +flycheck_* + +cppcheck_report.txt +comma*.sh + +selfdrive/modeld/thneed/compile +selfdrive/modeld/models/*.thneed +selfdrive/modeld/models/*.pkl + +*.bz2 + +build/ + +!**/.gitkeep + +poetry.toml +Pipfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..d716510 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,252 @@ +def retryWithDelay(int maxRetries, int delay, Closure body) { + for (int i = 0; i < maxRetries; i++) { + try { + return body() + } catch (Exception e) { + sleep(delay) + } + } + throw Exception("Failed after ${maxRetries} retries") +} + +def device(String ip, String step_label, String cmd) { + withCredentials([file(credentialsId: 'id_rsa', variable: 'key_file')]) { + def ssh_cmd = """ +ssh -tt -o ConnectTimeout=5 -o ServerAliveInterval=5 -o ServerAliveCountMax=2 -o BatchMode=yes -o StrictHostKeyChecking=no -i ${key_file} 'comma@${ip}' /usr/bin/bash <<'END' + +set -e + +shopt -s huponexit # kill all child processes when the shell exits + +export CI=1 +export PYTHONWARNINGS=error +export LOGPRINT=debug +export TEST_DIR=${env.TEST_DIR} +export SOURCE_DIR=${env.SOURCE_DIR} +export GIT_BRANCH=${env.GIT_BRANCH} +export GIT_COMMIT=${env.GIT_COMMIT} +export AZURE_TOKEN='${env.AZURE_TOKEN}' +export MAPBOX_TOKEN='${env.MAPBOX_TOKEN}' +# only use 1 thread for tici tests since most require HIL +export PYTEST_ADDOPTS="-n 0" + + +export GIT_SSH_COMMAND="ssh -i /data/gitkey" + +source ~/.bash_profile +if [ -f /TICI ]; then + source /etc/profile + + rm -rf /tmp/tmp* + rm -rf ~/.commacache + rm -rf /dev/shm/* + + if ! systemctl is-active --quiet systemd-resolved; then + echo "restarting resolved" + sudo systemctl start systemd-resolved + sleep 3 + fi + + # restart aux USB + if [ -e /sys/bus/usb/drivers/hub/3-0:1.0 ]; then + echo "restarting aux usb" + echo "3-0:1.0" | sudo tee /sys/bus/usb/drivers/hub/unbind + sleep 0.5 + echo "3-0:1.0" | sudo tee /sys/bus/usb/drivers/hub/bind + fi +fi +if [ -f /data/openpilot/launch_env.sh ]; then + source /data/openpilot/launch_env.sh +fi + +ln -snf ${env.TEST_DIR} /data/pythonpath + +cd ${env.TEST_DIR} || true +${cmd} +exit 0 + +END""" + + sh script: ssh_cmd, label: step_label + } +} + +def deviceStage(String stageName, String deviceType, List extra_env, def steps) { + stage(stageName) { + if (currentBuild.result != null) { + return + } + + def extra = extra_env.collect { "export ${it}" }.join('\n'); + def branch = env.BRANCH_NAME ?: 'master'; + + lock(resource: "", label: deviceType, inversePrecedence: true, variable: 'device_ip', quantity: 1, resourceSelectStrategy: 'random') { + docker.image('ghcr.io/commaai/alpine-ssh').inside('--user=root') { + timeout(time: 20, unit: 'MINUTES') { + retry (3) { + device(device_ip, "git checkout", extra + "\n" + readFile("selfdrive/test/setup_device_ci.sh")) + } + steps.each { item -> + device(device_ip, item[0], item[1]) + } + } + } + } + } +} + +def pcStage(String stageName, Closure body) { + node { + stage(stageName) { + if (currentBuild.result != null) { + return + } + + checkout scm + + def dockerArgs = "--user=batman -v /tmp/comma_download_cache:/tmp/comma_download_cache -v /tmp/scons_cache:/tmp/scons_cache -e PYTHONPATH=${env.WORKSPACE} --cpus=8 --memory 16g -e PYTEST_ADDOPTS='-n8'"; + + def openpilot_base = retryWithDelay (3, 15) { + return docker.build("openpilot-base:build-${env.GIT_COMMIT}", "-f Dockerfile.openpilot_base .") + } + + lock(resource: "", label: 'pc', inversePrecedence: true, quantity: 1) { + openpilot_base.inside(dockerArgs) { + timeout(time: 20, unit: 'MINUTES') { + try { + retryWithDelay (3, 15) { + sh "git config --global --add safe.directory '*'" + sh "git submodule update --init --recursive" + sh "git lfs pull" + } + body() + } finally { + sh "rm -rf ${env.WORKSPACE}/* || true" + sh "rm -rf .* || true" + } + } + } + } + } + } +} + +def setupCredentials() { + withCredentials([ + string(credentialsId: 'azure_token', variable: 'AZURE_TOKEN'), + string(credentialsId: 'mapbox_token', variable: 'MAPBOX_TOKEN') + ]) { + env.AZURE_TOKEN = "${AZURE_TOKEN}" + env.MAPBOX_TOKEN = "${MAPBOX_TOKEN}" + } +} + + +node { + env.CI = "1" + env.PYTHONWARNINGS = "error" + env.TEST_DIR = "/data/openpilot" + env.SOURCE_DIR = "/data/openpilot_source/" + setupCredentials() + + env.GIT_BRANCH = checkout(scm).GIT_BRANCH + env.GIT_COMMIT = checkout(scm).GIT_COMMIT + + def excludeBranches = ['master-ci', 'devel', 'devel-staging', 'release3', 'release3-staging', + 'testing-closet*', 'hotfix-*'] + def excludeRegex = excludeBranches.join('|').replaceAll('\\*', '.*') + + if (env.BRANCH_NAME != 'master') { + properties([ + disableConcurrentBuilds(abortPrevious: true) + ]) + } + + try { + if (env.BRANCH_NAME == 'devel-staging') { + deviceStage("build release3-staging", "tici-needs-can", [], [ + ["build release3-staging", "RELEASE_BRANCH=release3-staging $SOURCE_DIR/release/build_release.sh"], + ]) + } + + if (env.BRANCH_NAME == 'master-ci') { + deviceStage("build nightly", "tici-needs-can", [], [ + ["build nightly", "RELEASE_BRANCH=nightly $SOURCE_DIR/release/build_release.sh"], + ]) + } + + if (!env.BRANCH_NAME.matches(excludeRegex)) { + parallel ( + // tici tests + 'onroad tests': { + deviceStage("onroad", "tici-needs-can", [], [ + // TODO: ideally, this test runs in master-ci, but it takes 5+m to build it + //["build master-ci", "cd $SOURCE_DIR/release && TARGET_DIR=$TEST_DIR $SOURCE_DIR/scripts/retry.sh ./build_devel.sh"], + ["build openpilot", "cd selfdrive/manager && ./build.py"], + ["check dirty", "release/check-dirty.sh"], + ["onroad tests", "pytest selfdrive/test/test_onroad.py -s"], + ["time to onroad", "pytest selfdrive/test/test_time_to_onroad.py"], + ]) + }, + 'HW + Unit Tests': { + deviceStage("tici-hardware", "tici-common", ["UNSAFE=1"], [ + ["build", "cd selfdrive/manager && ./build.py"], + ["test pandad", "pytest selfdrive/boardd/tests/test_pandad.py"], + ["test power draw", "pytest -s system/hardware/tici/tests/test_power_draw.py"], + ["test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py"], + ["test pigeond", "pytest system/sensord/tests/test_pigeond.py"], + ["test manager", "pytest selfdrive/manager/test/test_manager.py"], + ]) + }, + 'loopback': { + deviceStage("loopback", "tici-loopback", ["UNSAFE=1"], [ + ["build openpilot", "cd selfdrive/manager && ./build.py"], + ["test boardd loopback", "pytest selfdrive/boardd/tests/test_boardd_loopback.py"], + ]) + }, + 'camerad': { + deviceStage("AR0231", "tici-ar0231", ["UNSAFE=1"], [ + ["build", "cd selfdrive/manager && ./build.py"], + ["test camerad", "pytest system/camerad/test/test_camerad.py"], + ["test exposure", "pytest system/camerad/test/test_exposure.py"], + ]) + deviceStage("OX03C10", "tici-ox03c10", ["UNSAFE=1"], [ + ["build", "cd selfdrive/manager && ./build.py"], + ["test camerad", "pytest system/camerad/test/test_camerad.py"], + ["test exposure", "pytest system/camerad/test/test_exposure.py"], + ]) + }, + 'sensord': { + deviceStage("LSM + MMC", "tici-lsmc", ["UNSAFE=1"], [ + ["build", "cd selfdrive/manager && ./build.py"], + ["test sensord", "pytest system/sensord/tests/test_sensord.py"], + ]) + deviceStage("BMX + LSM", "tici-bmx-lsm", ["UNSAFE=1"], [ + ["build", "cd selfdrive/manager && ./build.py"], + ["test sensord", "pytest system/sensord/tests/test_sensord.py"], + ]) + }, + 'replay': { + deviceStage("model-replay", "tici-replay", ["UNSAFE=1"], [ + ["build", "cd selfdrive/manager && ./build.py"], + ["model replay", "selfdrive/test/process_replay/model_replay.py"], + ]) + }, + 'tizi': { + deviceStage("tizi", "tizi", ["UNSAFE=1"], [ + ["build openpilot", "cd selfdrive/manager && ./build.py"], + ["test boardd loopback", "SINGLE_PANDA=1 pytest selfdrive/boardd/tests/test_boardd_loopback.py"], + ["test pandad", "pytest selfdrive/boardd/tests/test_pandad.py"], + ["test amp", "pytest system/hardware/tici/tests/test_amplifier.py"], + ["test hw", "pytest system/hardware/tici/tests/test_hardware.py"], + ["test qcomgpsd", "pytest system/qcomgpsd/tests/test_qcomgpsd.py"], + ]) + }, + + ) + } + } catch (Exception e) { + currentBuild.result = 'FAILED' + throw e + } +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7dafa94 --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2018, Comma.ai, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..db74ee6 --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +[](https://comma.ai/shop/comma-3x) + +What is openpilot? +------ + +[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, openpilot performs the functions of Adaptive Cruise Control (ACC), Automated Lane Centering (ALC), Forward Collision Warning (FCW), and Lane Departure Warning (LDW) for a growing variety of [supported car makes, models, and model years](docs/CARS.md). In addition, while openpilot is engaged, a camera-based Driver Monitoring (DM) feature alerts distracted and asleep drivers. See more about [the vehicle integration](docs/INTEGRATION.md) and [limitations](docs/LIMITATIONS.md). + +
+
+
+[](https://codecov.io/gh/commaai/openpilot)
diff --git a/RELEASES.md b/RELEASES.md
new file mode 100644
index 0000000..0a86600
--- /dev/null
+++ b/RELEASES.md
@@ -0,0 +1,1014 @@
+Version 0.9.6 (2024-02-27)
+========================
+* New driving model
+ * Vision model trained on more data
+ * Improved driving performance
+ * Directly outputs curvature for lateral control
+* New driver monitoring model
+ * Trained on larger dataset
+* AGNOS 9
+* comma body streaming and controls over WebRTC
+* Improved fuzzy fingerprinting for many makes and models
+* Alpha longitudinal support for new Toyota models
+* Chevrolet Equinox 2019-22 support thanks to JasonJShuler and nworb-cire!
+* Dodge Durango 2020-21 support
+* Hyundai Staria 2023 support thanks to sunnyhaibin!
+* Kia Niro Plug-in Hybrid 2022 support thanks to sunnyhaibin!
+* Lexus LC 2024 support thanks to nelsonjchen!
+* Toyota RAV4 2023-24 support
+* Toyota RAV4 Hybrid 2023-24 support
+
+Version 0.9.5 (2023-11-17)
+========================
+* New driving model
+ * Improved navigate on openpilot performance using navigation instructions as an additional model input
+ * Do lateral planning inside the model
+ * New vision transformer architecture
+* Cadillac Escalade ESV 2019 support thanks to twilsonco!
+* Hyundai Azera 2022 support thanks to sunnyhaibin!
+* Hyundai Azera Hybrid 2020 support thanks to chanhojung and haram-KONA!
+* Hyundai Custin 2023 support thanks to sunnyhaibin and Saber422!
+* Hyundai Ioniq 6 2023 support thanks to sunnyhaibin and alamo3!
+* Hyundai Kona Electric 2023 (Korean version) support thanks to sunnyhaibin and haram-KONA!
+* Kia K8 Hybrid (with HDA II) 2023 support thanks to sunnyhaibin!
+* Kia Optima Hybrid 2019 support
+* Kia Sorento Hybrid 2023 support thanks to sunnyhaibin!
+* Lexus GS F 2016 support thanks to snyperifle!
+* Lexus IS 2023 support thanks to L3R5!
+
+Version 0.9.4 (2023-07-27)
+========================
+* comma 3X support
+* Navigate on openpilot in Experimental mode
+ * When navigation has a destination, openpilot will input the map information into the model, which provides useful context to help the model understand the scene
+ * When navigating on openpilot, openpilot will keep left or right appropriately at forks and exits
+ * When navigating on openpilot, lane change behavior is unchanged and still activated by the driver
+ * When navigate on openpilot is active, the path on the map is green
+* UI updates
+ * Navigation settings moved to home screen and map
+ * Border color always shows engagement status. Blue means disengaged, green means engaged, and grey means engaged with human overriding
+ * Alerts are shown inside the border. Black means info, orange means warning, and red means critical alert
+* Bookmarked segments are preserved on the device's storage
+* Ford Focus 2018 support
+* Kia Carnival 2023 support thanks to sunnyhaibin!
+
+Version 0.9.3 (2023-06-29)
+========================
+* New driving model
+ * Improved height estimation and added height tracking in liveCalibration
+ * Model inputs refactor
+* New driving personality setting
+ * Three settings: aggressive, standard, and relaxed
+ * Standard is recommended and the default
+ * In aggressive mode, lead follow distance is shorter and acceleration response is quicker
+ * In relaxed mode, lead follow distance is longer
+* Improved fuzzy fingerprinting for Hyundai, Kia, and Genesis
+* Improved thermal management logic
+
+Version 0.9.2 (2023-05-22)
+========================
+* New driving model
+ * Reduced turn diving
+ * Trained on a new dataset
+* UI updates
+ * New experimental mode visualization
+ * Draw MPC path instead of model-predicted path
+* AGNOS 7
+ * Faster boot time
+ * Fixes rare no sounds bug
+ * Fixes bootsplash bug at extreme temperatures
+* Buick LaCrosse 2017-19 support thanks to koch-cf!
+* Chevrolet Trailblazer 2021-22 support thanks to TurboCE!
+* Ford Bronco Sport 2021-22 support
+* Ford Escape 2020-22 support
+* Ford Explorer 2020-22 support
+* Ford Kuga 2020-22 support
+* Ford Maverick 2022-23 support
+* Genesis GV80 2023 support thanks to JWingate80!
+* Honda HR-V 2023 support thanks to AlexandreSato and galegozi!
+* Kia Niro EV 2023 support thanks to JosselinLecocq!
+* Lexus ES 2017-18 support
+* Lincoln Aviator 2021 support
+* Å koda Fabia 2022-23 support thanks to jyoung8607!
+
+
+Version 0.9.1 (2023-02-28)
+========================
+* New driving model
+ * 30% improved height estimation resulting in better driving performance for tall cars
+* Driver monitoring: removed timer resetting on user interaction if distracted
+* UI updates
+ * Adjust alert volume using ambient noise level
+ * Driver monitoring icon shows driver's head pose
+ * German translation thanks to Vrabetz and CzokNorris!
+* Cadillac Escalade 2017 support thanks to rickygilleland!
+* Chevrolet Bolt EV 2022-23 support thanks to JasonJShuler!
+* Genesis GV60 2023 support thanks to sunnyhaibin!
+* Hyundai Tucson 2022-23 support
+* Kia K5 Hybrid 2020 support thanks to sunnyhaibin!
+* Kia Niro Hybrid 2023 support thanks to sunnyhaibin!
+* Kia Sorento 2022-23 support thanks to sunnyhaibin!
+* Kia Sorento Plug-in Hybrid 2022 support thanks to sunnyhaibin!
+* Toyota C-HR 2021 support thanks to eFiniLan!
+* Toyota C-HR Hybrid 2022 support thanks to Korben00!
+* Volkswagen Crafter and MAN TGE 2017-23 support thanks to jyoung8607!
+
+Version 0.9.0 (2022-11-21)
+========================
+* New driving model
+ * Internal feature space information content increased tenfold during training to ~700 bits, which makes the model dramatically more accurate
+ * Less reliance on previous frames makes model more reactive and snappy
+ * Trained in new reprojective simulator
+ * Trained in 36 hours from scratch, compared to one week for previous releases
+ * Training now simulates both lateral and longitudinal behavior, which allows openpilot to slow down for turns, stop at traffic lights, and more in experimental mode
+* Experimental driving mode
+ * End-to-end longitudinal control
+ * Stops for traffic lights and stop signs
+ * Slows down for turns
+ * openpilot defaults to chill mode, enable experimental mode in settings
+* Driver monitoring updates
+ * New bigger model with added end-to-end distracted trigger
+ * Reduced false positives during driver calibration
+* Self-tuning torque controller: learns parameters live for each car
+* Torque controller used on all Toyota, Lexus, Hyundai, Kia, and Genesis models
+* UI updates
+ * Matched speeds shown on car's dash
+ * Multi-language in navigation
+ * Improved update experience
+ * Border turns grey while overriding steering
+ * Bookmark events while driving; view them in comma connect
+ * New onroad visualization for experimental mode
+* tools: new and improved cabana thanks to deanlee!
+* Experimental longitudinal support for Volkswagen, CAN-FD Hyundai, and new GM models
+* Genesis GV70 2022-23 support thanks to zunichky and sunnyhaibin!
+* Hyundai Santa Cruz 2021-22 support thanks to sunnyhaibin!
+* Kia Sportage 2023 support thanks to sunnyhaibin!
+* Kia Sportage Hybrid 2023 support thanks to sunnyhaibin!
+* Kia Stinger 2022 support thanks to sunnyhaibin!
+
+Version 0.8.16 (2022-08-26)
+========================
+* New driving model
+ * Reduced turn cutting
+* Auto-detect right hand drive setting with driver monitoring model
+* Improved fan controller for comma three
+* New translations
+ * Japanese thanks to cydia2020!
+ * Brazilian Portuguese thanks to AlexandreSato!
+* Chevrolet Bolt EUV 2022-23 support thanks to JasonJShuler!
+* Chevrolet Silverado 1500 2020-21 support thanks to JasonJShuler!
+* GMC Sierra 1500 2020-21 support thanks to JasonJShuler!
+* Hyundai Ioniq 5 2022 support thanks to sunnyhaibin!
+* Hyundai Kona Electric 2022 support thanks to sunnyhaibin!
+* Hyundai Tucson Hybrid 2022 support thanks to sunnyhaibin!
+* Subaru Legacy 2020-22 support thanks to martinl!
+* Subaru Outback 2020-22 support
+
+Version 0.8.15 (2022-07-20)
+========================
+* New driving model
+ * Path planning uses end-to-end output instead of lane lines at all times
+ * Reduced ping pong
+ * Improved lane centering
+* New lateral controller based on physical wheel torque model
+ * Much smoother control that's consistent across the speed range
+ * Effective feedforward that uses road roll
+ * Simplified tuning, all car-specific parameters can be derived from data
+ * Used on select Toyota and Hyundai models at first
+ * Significantly improved control on TSS-P Prius
+* New driver monitoring model
+ * Bigger model, covering full interior view from driver camera
+ * Works with a wider variety of mounting angles
+ * 3x more unique comma three training data than previous
+* Navigation improvements
+ * Speed limits shown while navigating
+ * Faster position fix by using raw GPS measurements
+* UI updates
+ * Multilanguage support for settings and home screen
+ * New font
+ * Refreshed max speed design
+ * More consistent camera view perspective across cars
+* Reduced power usage: device runs cooler and fan spins less
+* AGNOS 5
+ * Support VSCode remote SSH target
+ * Support for delta updates to reduce data usage on future OS updates
+* Chrysler ECU firmware fingerprinting thanks to realfast!
+* Honda Civic 2022 support
+* Hyundai Tucson 2021 support thanks to bluesforte!
+* Kia EV6 2022 support
+* Lexus NX Hybrid 2020 support thanks to AlexandreSato!
+* Ram 1500 2019-21 support thanks to realfast!
+
+Version 0.8.14 (2022-06-01)
+========================
+ * New driving model
+ * Bigger model, using both of comma three's road-facing cameras
+ * Better at cut-in detection and tight turns
+ * New driver monitoring model
+ * Tweaked network structure to improve output resolution for DSP
+ * Fixed bug in quantization aware training to reduce quantizing errors
+ * Resulted in 7x less MSE and no more random biases at runtime
+ * Added toggle to disable disengaging on the accelerator pedal
+ * comma body support
+ * Audi RS3 support thanks to jyoung8607!
+ * Hyundai Ioniq Plug-in Hybrid 2019 support thanks to sunnyhaibin!
+ * Hyundai Tucson Diesel 2019 support thanks to sunnyhaibin!
+ * Toyota Alphard Hybrid 2021 support
+ * Toyota Avalon Hybrid 2022 support
+ * Toyota RAV4 2022 support
+ * Toyota RAV4 Hybrid 2022 support
+
+Version 0.8.13 (2022-02-18)
+========================
+ * Improved driver monitoring
+ * Re-tuned driver pose learner for relaxed driving positions
+ * Added reliance on driving model to be more scene adaptive
+ * Matched strictness between comma two and comma three
+ * Improved performance in turns by compensating for the road bank angle
+ * Improved camera focus on the comma two
+ * AGNOS 4
+ * ADB support
+ * improved cell auto configuration
+ * NEOS 19
+ * package updates
+ * stability improvements
+ * Subaru ECU firmware fingerprinting thanks to martinl!
+ * Hyundai Santa Fe Plug-in Hybrid 2022 support thanks to sunnyhaibin!
+ * Mazda CX-5 2022 support thanks to Jafaral!
+ * Subaru Impreza 2020 support thanks to martinl!
+ * Toyota Avalon 2022 support thanks to sshane!
+ * Toyota Prius v 2017 support thanks to CT921!
+ * Volkswagen Caravelle 2020 support thanks to jyoung8607!
+
+Version 0.8.12 (2021-12-15)
+========================
+ * New driving model
+ * Improved behavior around exits
+ * Better pose accuracy at high speeds, allowing max speed of 90mph
+ * Fully incorporated comma three data into all parts of training stack
+ * Improved follow distance
+ * Better longitudinal policy, especially in low speed traffic
+ * New alert sounds
+ * AGNOS 3
+ * Display burn in mitigation
+ * Improved audio amplifier configuration
+ * System reliability improvements
+ * Update Python to 3.8.10
+ * Raw logs upload moved to connect.comma.ai
+ * Fixed HUD alerts on newer Honda Bosch thanks to csouers!
+ * Audi Q3 2020-21 support thanks to jyoung8607!
+ * Lexus RC 2020 support thanks to ErichMoraga!
+
+Version 0.8.11 (2021-11-29)
+========================
+ * Support for CAN FD on the red panda
+ * Support for an external panda on the comma three
+ * Navigation: Show more detailed instructions when approaching maneuver
+ * Fixed occasional steering faults on GM cars thanks to jyoung8607!
+ * Nissan ECU firmware fingerprinting thanks to robin-reckmann, martinl, and razem-io!
+ * Cadillac Escalade ESV 2016 support thanks to Gibby!
+ * Genesis G70 2020 support thanks to tecandrew!
+ * Hyundai Santa Fe Hybrid 2022 support thanks to sunnyhaibin!
+ * Mazda CX-9 2021 support thanks to Jacar!
+ * Volkswagen Polo 2020 support thanks to jyoung8607!
+ * Volkswagen T-Roc 2021 support thanks to jyoung8607!
+
+Version 0.8.10 (2021-11-01)
+========================
+ * New driving model
+ * Trained on one million minutes!!!
+ * Fixed lead training making lead predictions significantly more accurate
+ * Fixed several localizer dataset bugs and loss function bugs, overall improved accuracy
+ * New driver monitoring model
+ * Trained on latest data from both comma two and comma three
+ * Increased model field of view by 40% on comma three
+ * Improved model stability on masked users
+ * Improved pose prediction with reworked ground-truth stack
+ * Lateral and longitudinal planning MPCs now in ACADOS
+ * Combined longitudinal MPCs
+ * All longitudinal planning now happens in a single MPC system
+ * Fixed instability in MPC problem to prevent sporadic CPU usage
+ * AGNOS 2: minor stability improvements and builder repo open sourced
+ * tools: new and improved replay thanks to deanlee!
+ * Moved community-supported cars outside of the Community Features toggle
+ * Improved FW fingerprinting reliability for Hyundai/Kia/Genesis
+ * Added prerequisites for longitudinal control on Hyundai/Kia/Genesis and Honda Bosch
+ * Audi S3 2015 support thanks to jyoung8607!
+ * Honda Freed 2020 support thanks to belm0!
+ * Hyundai Ioniq Hybrid 2020-2022 support thanks to sunnyhaibin!
+ * Hyundai Santa Fe 2022 support thanks to sunnyhaibin!
+ * Kia K5 2021 support thanks to sunnyhaibin!
+ * Å koda Kamiq 2021 support thanks to jyoung8607!
+ * Å koda Karoq 2019 support thanks to jyoung8607!
+ * Volkswagen Arteon 2021 support thanks to jyoung8607!
+ * Volkswagen California 2021 support thanks to jyoung8607!
+ * Volkswagen Taos 2022 support thanks to jyoung8607!
+
+Version 0.8.9 (2021-09-14)
+========================
+ * Improved fan control on comma three
+ * AGNOS 1.5: improved stability
+ * Honda e 2020 support
+
+Version 0.8.8 (2021-08-27)
+========================
+ * New driving model with improved laneless performance
+ * Trained on 5000+ hours of diverse driving data from 3000+ users in 40+ countries
+ * Better anti-cheating methods during simulator training ensure the model hugs less when in laneless mode
+ * All new desire ground-truthing stack makes the model better at lane changes
+ * New driver monitoring model: improved performance on comma three
+ * NEOS 18 for comma two: update packages
+ * AGNOS 1.3 for comma three: fix display init at high temperatures
+ * Improved auto-exposure on comma three
+ * Improved longitudinal control on Honda Nidec cars
+ * Hyundai Kona Hybrid 2020 support thanks to haram-KONA!
+ * Hyundai Sonata Hybrid 2021 support thanks to Matt-Wash-Burn!
+ * Kia Niro Hybrid 2021 support thanks to tetious!
+
+Version 0.8.7 (2021-07-31)
+========================
+ * comma three support!
+ * Navigation alpha for the comma three!
+ * Volkswagen T-Cross 2021 support thanks to jyoung8607!
+
+Version 0.8.6 (2021-07-21)
+========================
+ * Revamp lateral and longitudinal planners
+ * Refactor planner output API to be more readable and verbose
+ * Planners now output desired trajectories for speed, acceleration, curvature, and curvature rate
+ * Use MPC for longitudinal planning when no lead car is present, makes accel and decel smoother
+ * Remove "CHECK DRIVER FACE VISIBILITY" warning
+ * Fixed cruise fault on some TSS2.5 Camrys and international Toyotas
+ * Hyundai Elantra Hybrid 2021 support thanks to tecandrew!
+ * Hyundai Ioniq PHEV 2020 support thanks to YawWashout!
+ * Kia Niro Hybrid 2019 support thanks to jyoung8607!
+ * Å koda Octavia RS 2016 support thanks to jyoung8607!
+ * Toyota Alphard 2020 support thanks to belm0!
+ * Volkswagen Golf SportWagen 2015 support thanks to jona96!
+ * Volkswagen Touran 2017 support thanks to jyoung8607!
+
+Version 0.8.5 (2021-06-11)
+========================
+ * NEOS update: improved reliability and stability with better voltage regulator configuration
+ * Smart model-based Forward Collision Warning
+ * CAN-based fingerprinting moved behind community features toggle
+ * Improved longitudinal control on Toyotas with a comma pedal
+ * Improved auto-brightness using road-facing camera
+ * Added "Software" settings page with updater controls
+ * Audi Q2 2018 support thanks to jyoung8607!
+ * Hyundai Elantra 2021 support thanks to CruiseBrantley!
+ * Lexus UX Hybrid 2019-2020 support thanks to brianhaugen2!
+ * Toyota Avalon Hybrid 2019 support thanks to jbates9011!
+ * SEAT Leon 2017 & 2020 support thanks to jyoung8607!
+ * Å koda Octavia 2015 & 2019 support thanks to jyoung8607!
+
+Version 0.8.4 (2021-05-17)
+========================
+ * Delay controls start until system is ready
+ * Fuzzy car identification, enabled with Community Features toggle
+ * Localizer optimized for increased precision and less CPU usage
+ * Re-tuned lateral control to be more aggressive when model is confident
+ * Toyota Mirai 2021 support
+ * Lexus NX 300 2020 support thanks to goesreallyfast!
+ * Volkswagen Atlas 2018-19 support thanks to jyoung8607!
+
+Version 0.8.3 (2021-04-01)
+========================
+ * New model
+ * Trained on new diverse dataset from 2000+ users from 30+ countries
+ * Trained with improved segnet from the comma-pencil community project
+ * 🥬 Dramatically improved end-to-end lateral performance 🥬
+ * Toggle added to disable the use of lanelines
+ * NEOS update: update packages and support for new UI
+ * New offroad UI based on Qt
+ * Default SSH key only used for setup
+ * Kia Ceed 2019 support thanks to ZanZaD13!
+ * Kia Seltos 2021 support thanks to speedking456!
+ * Added support for many Volkswagen and Å koda models thanks to jyoung8607!
+
+Version 0.8.2 (2021-02-26)
+========================
+ * Use model points directly in MPC (no more polyfits), making lateral planning more accurate
+ * Use model heading prediction for smoother lateral control
+ * Smarter actuator delay compensation
+ * Improve qcamera resolution for improved video in explorer and connect
+ * Adjust maximum engagement speed to better fit the model's training distribution
+ * New driver monitoring model trained with 3x more diverse data
+ * Improved face detection with masks
+ * More predictable DM alerts when visibility is bad
+ * Rewritten video streaming between openpilot processes
+ * Improved longitudinal tuning on TSS2 Corolla and Rav4 thanks to briskspirit!
+ * Audi A3 2015 and 2017 support thanks to keeleysam!
+ * Nissan Altima 2020 support thanks to avolmensky!
+ * Lexus ES Hybrid 2018 support thanks to TheInventorMan!
+ * Toyota Camry Hybrid 2021 support thanks to alancyau!
+
+Version 0.8.1 (2020-12-21)
+========================
+ * Original EON is deprecated, upgrade to comma two
+ * Better model performance in heavy rain
+ * Better lane positioning in turns
+ * Fixed bug where model would cut turns on empty roads at night
+ * Fixed issue where some Toyotas would not completely stop thanks to briskspirit!
+ * Toyota Camry 2021 with TSS2.5 support
+ * Hyundai Ioniq Electric 2020 support thanks to baldwalker!
+
+Version 0.8.0 (2020-11-30)
+========================
+ * New driving model: fully 3D and improved cut-in detection
+ * UI draws 2 road edges, 4 lanelines and paths in 3D
+ * Major fixes to cut-in detection for openpilot longitudinal
+ * Grey panda is no longer supported, upgrade to comma two or black panda
+ * Lexus NX 2018 support thanks to matt12eagles!
+ * Kia Niro EV 2020 support thanks to nickn17!
+ * Toyota Prius 2021 support thanks to rav4kumar!
+ * Improved lane positioning with uncertain lanelines, wide lanes and exits
+ * Improved lateral control for Prius and Subaru
+
+Version 0.7.10 (2020-10-29)
+========================
+ * Grey panda is deprecated, upgrade to comma two or black panda
+ * NEOS update: update to Python 3.8.2 and lower CPU frequency
+ * Improved thermals due to reduced CPU frequency
+ * Update SNPE to 1.41.0
+ * Reduced offroad power consumption
+ * Various system stability improvements
+ * Acura RDX 2020 support thanks to csouers!
+
+Version 0.7.9 (2020-10-09)
+========================
+ * Improved car battery power management
+ * Improved updater robustness
+ * Improved realtime performance
+ * Reduced UI and modeld lags
+ * Increased torque on 2020 Hyundai Sonata and Palisade
+
+Version 0.7.8 (2020-08-19)
+========================
+ * New driver monitoring model: improved face detection and better compatibility with sunglasses
+ * Download NEOS operating system updates in the background
+ * Improved updater reliability and responsiveness
+ * Hyundai Kona 2020, Veloster 2019, and Genesis G70 2018 support thanks to xps-genesis!
+
+Version 0.7.7 (2020-07-20)
+========================
+ * White panda is no longer supported, upgrade to comma two or black panda
+ * Improved vehicle model estimation using high precision localizer
+ * Improved thermal management on comma two
+ * Improved autofocus for road-facing camera
+ * Improved noise performance for driver-facing camera
+ * Block lane change start using blindspot monitor on select Toyota, Hyundai, and Subaru
+ * Fix GM ignition detection
+ * Code cleanup and smaller release sizes
+ * Hyundai Sonata 2020 promoted to officially supported car
+ * Hyundai Ioniq Electric Limited 2019 and Ioniq SE 2020 support thanks to baldwalker!
+ * Subaru Forester 2019 and Ascent 2019 support thanks to martinl!
+
+Version 0.7.6.1 (2020-06-16)
+========================
+ * Hotfix: update kernel on some comma twos (orders #8570-#8680)
+
+Version 0.7.6 (2020-06-05)
+========================
+ * White panda is deprecated, upgrade to comma two or black panda
+ * 2017 Nissan X-Trail, 2018-19 Leaf and 2019 Rogue support thanks to avolmensky!
+ * 2017 Mazda CX-5 support in dashcam mode thanks to Jafaral!
+ * Huge CPU savings in modeld by using thneed!
+ * Lots of code cleanup and refactors
+
+Version 0.7.5 (2020-05-13)
+========================
+ * Right-Hand Drive support for both driving and driver monitoring!
+ * New driving model: improved at sharp turns and lead speed estimation
+ * New driver monitoring model: overall improvement on comma two
+ * Driver camera preview in settings to improve mounting position
+ * Added support for many Hyundai, Kia, Genesis models thanks to xx979xx!
+ * Improved lateral tuning for 2020 Toyota Rav 4 (hybrid)
+
+Version 0.7.4 (2020-03-20)
+========================
+ * New driving model: improved lane changes and lead car detection
+ * Improved driver monitoring model: improve eye detection
+ * Improved calibration stability
+ * Improved lateral control on some 2019 and 2020 Toyota Prius
+ * Improved lateral control on VW Golf: 20% more steering torque
+ * Fixed bug where some 2017 and 2018 Toyota C-HR would use the wrong steering angle sensor
+ * Support for Honda Insight thanks to theantihero!
+ * Code cleanup in car abstraction layers and ui
+
+Version 0.7.3 (2020-02-21)
+========================
+ * Support for 2020 Highlander thanks to che220!
+ * Support for 2018 Lexus NX 300h thanks to kengggg!
+ * Speed up ECU firmware query
+ * Fix bug where manager would sometimes hang after shutting down the car
+
+Version 0.7.2 (2020-02-07)
+========================
+ * ECU firmware version based fingerprinting for Honda & Toyota
+ * New driving model: improved path prediction during turns and lane changes and better lead speed tracking
+ * Improve driver monitoring under extreme lighting and add low accuracy alert
+ * Support for 2019 Rav4 Hybrid thanks to illumiN8i!
+ * Support for 2016, 2017 and 2020 Lexus RX thanks to illumiN8i!
+ * Support for 2020 Chrysler Pacifica Hybrid thanks to adhintz!
+
+Version 0.7.1 (2020-01-20)
+========================
+ * comma two support!
+ * Lane Change Assist above 45 mph!
+ * Replace zmq with custom messaging library, msgq!
+ * Supercombo model: calibration and driving models are combined for better lead estimate
+ * More robust updater thanks to jyoung8607! Requires NEOS update
+ * Improve low speed ACC tuning
+
+Version 0.7 (2019-12-13)
+========================
+ * Move to SCons build system!
+ * Add Lane Departure Warning (LDW) for all supported vehicles!
+ * NEOS update: increase wifi speed thanks to jyoung8607!
+ * Adaptive driver monitoring based on scene
+ * New driving model trained end-to-end: improve lane lines and lead detection
+ * Smarter torque limit alerts for all cars
+ * Improve GM longitudinal control: proper computations for 15Hz radar
+ * Move GM port, Toyota with DSU removed, comma pedal in community features; toggle switch required
+ * Remove upload over cellular toggle: only upload qlog and qcamera files if not on wifi
+ * Refactor Panda code towards ISO26262 and SIL2 compliance
+ * Forward stock FCW for Honda Nidec
+ * Volkswagen port now standard: comma Harness intercepts stock camera
+
+Version 0.6.6 (2019-11-05)
+========================
+ * Volkswagen support thanks to jyoung8607!
+ * Toyota Corolla Hybrid with TSS 2.0 support thanks to u8511049!
+ * Lexus ES with TSS 2.0 support thanks to energee!
+ * Fix GM ignition detection and lock safety mode not required anymore
+ * Log panda firmware and dongle ID thanks to martinl!
+ * New driving model: improve path prediction and lead detection
+ * New driver monitoring model, 4x smaller and running on DSP
+ * Display an alert and don't start openpilot if panda has wrong firmware
+ * Fix bug preventing EON from terminating processes after a drive
+ * Remove support for Toyota giraffe without the 120Ohm resistor
+
+Version 0.6.5 (2019-10-07)
+========================
+ * NEOS update: upgrade to Python3 and new installer!
+ * comma Harness support!
+ * New driving model: improve path prediction
+ * New driver monitoring model: more accurate face and eye detection
+ * Redesign offroad screen to display updates and alerts
+ * Increase maximum allowed acceleration
+ * Prevent car 12V battery drain by cutting off EON charge after 3 days of no drive
+ * Lexus CT Hybrid support thanks to thomaspich!
+ * Louder chime for critical alerts
+ * Add toggle to switch to dashcam mode
+ * Fix "invalid vehicle params" error on DSU-less Toyota
+
+Version 0.6.4 (2019-09-08)
+========================
+ * Forward stock AEB for Honda Nidec
+ * Improve lane centering on banked roads
+ * Always-on forward collision warning
+ * Always-on driver monitoring, except for right hand drive countries
+ * Driver monitoring learns the user's normal driving position
+ * Honda Fit support thanks to energee!
+ * Lexus IS support
+
+Version 0.6.3 (2019-08-12)
+========================
+ * Alert sounds from EON: requires NEOS update
+ * Improve driver monitoring: eye tracking and improved awareness logic
+ * Improve path prediction with new driving model
+ * Improve lane positioning with wide lanes and exits
+ * Improve lateral control on RAV4
+ * Slow down for turns using model
+ * Open sourced regression test to verify outputs against reference logs
+ * Open sourced regression test to sanity check all car models
+
+Version 0.6.2 (2019-07-29)
+========================
+ * New driving model!
+ * Improve lane tracking with double lines
+ * Strongly improve stationary vehicle detection
+ * Strongly reduce cases of braking due to false leads
+ * Better lead tracking around turns
+ * Improve cut-in prediction by using neural network
+ * Improve lateral control on Toyota Camry and C-HR thanks to zorrobyte!
+ * Fix unintended openpilot disengagements on Jeep thanks to adhintz!
+ * Fix delayed transition to offroad when car is turned off
+
+Version 0.6.1 (2019-07-21)
+========================
+ * Remote SSH with comma prime and [ssh.comma.ai](https://ssh.comma.ai)
+ * Panda code Misra-c2012 compliance, tested against cppcheck coverage
+ * Lockout openpilot after 3 terminal alerts for driver distracted or unresponsive
+ * Toyota Sienna support thanks to wocsor!
+
+Version 0.6 (2019-07-01)
+========================
+ * New model, with double the pixels and ten times the temporal context!
+ * Car should not take exits when in the right lane
+ * openpilot uses only ~65% of the CPU (down from 75%)
+ * Routes visible in connect/explorer after only 0.2% is uploaded (qlogs)
+ * loggerd and sensord are open source, every line of openpilot is now open
+ * Panda safety code is MISRA compliant and ships with a signed version on release2
+ * New NEOS is 500MB smaller and has a reproducible usr/pipenv
+ * Lexus ES Hybrid support thanks to wocsor!
+ * Improve tuning for supported Toyota with TSS 2.0
+ * Various other stability improvements
+
+Version 0.5.13 (2019-05-31)
+==========================
+ * Reduce panda power consumption by 70%, down to 80mW, when car is off (not for GM)
+ * Reduce EON power consumption by 40%, down to 1100mW, when car is off
+ * Reduce CPU utilization by 20% and improve stability
+ * Temporarily remove mapd functionalities to improve stability
+ * Add openpilot record-only mode for unsupported cars
+ * Synchronize controlsd to boardd to reduce latency
+ * Remove panda support for Subaru giraffe
+
+Version 0.5.12 (2019-05-16)
+==========================
+ * Improve lateral control for the Prius and Prius Prime
+ * Compress logs before writing to disk
+ * Remove old driving data when storage reaches 90% full
+ * Fix small offset in following distance
+ * Various small CPU optimizations
+ * Improve offroad power consumption: require NEOS Update
+ * Add default speed limits for Estonia thanks to martinl!
+ * Subaru Crosstrek support thanks to martinl!
+ * Toyota Avalon support thanks to njbrown09!
+ * Toyota Rav4 with TSS 2.0 support thanks to wocsor!
+ * Toyota Corolla with TSS 2.0 support thanks to wocsor!
+
+Version 0.5.11 (2019-04-17)
+========================
+ * Add support for Subaru
+ * Reduce panda power consumption by 60% when car is off
+ * Fix controlsd lag every 6 minutes. This would sometimes cause disengagements
+ * Fix bug in controls with new angle-offset learner in MPC
+ * Reduce cpu consumption of ubloxd by rewriting it in C++
+ * Improve driver monitoring model and face detection
+ * Improve performance of visiond and ui
+ * Honda Passport 2019 support
+ * Lexus RX Hybrid 2019 support thanks to schomems!
+ * Improve road selection heuristic in mapd
+ * Add Lane Departure Warning to dashboard for Toyota thanks to arne182
+
+Version 0.5.10 (2019-03-19)
+========================
+ * Self-tuning vehicle parameters: steering offset, tire stiffness and steering ratio
+ * Improve longitudinal control at low speed when lead vehicle harshly decelerates
+ * Fix panda bug going unexpectedly in DCP mode when EON is connected
+ * Reduce white panda power consumption by 500mW when EON is disconnected by turning off WIFI
+ * New Driver Monitoring Model
+ * Support QR codes for login using comma connect
+ * Refactor comma pedal FW and use CRC-8 checksum algorithm for safety. Reflashing pedal is required.
+ Please see `#hw-pedal` on [discord](discord.comma.ai) for assistance updating comma pedal.
+ * Additional speed limit rules for Germany thanks to arne182
+ * Allow negative speed limit offsets
+
+Version 0.5.9 (2019-02-10)
+========================
+ * Improve calibration using a dedicated neural network
+ * Abstract planner in its own process to remove lags in controls process
+ * Improve speed limits with country/region defaults by road type
+ * Reduce mapd data usage with gzip thanks to eFiniLan
+ * Zip log files in the background to reduce disk usage
+ * Kia Optima support thanks to emmertex!
+ * Buick Regal 2018 support thanks to HOYS!
+ * Comma pedal support for Toyota thanks to wocsor! Note: tuning needed and not maintained by comma
+ * Chrysler Pacifica and Jeep Grand Cherokee support thanks to adhintz!
+
+Version 0.5.8 (2019-01-17)
+========================
+ * Open sourced visiond
+ * Auto-slowdown for upcoming turns
+ * Chrysler/Jeep/Fiat support thanks to adhintz!
+ * Honda Civic 2019 support thanks to csouers!
+ * Improve use of car display in Toyota thanks to arne182!
+ * No data upload when connected to Android or iOS hotspots and "Enable Upload Over Cellular" setting is off
+ * EON stops charging when 12V battery drops below 11.8V
+
+Version 0.5.7 (2018-12-06)
+========================
+ * Speed limit from OpenStreetMap added to UI
+ * Highlight speed limit when speed exceeds road speed limit plus a delta
+ * Option to limit openpilot max speed to road speed limit plus a delta
+ * Cadillac ATS support thanks to vntarasov!
+ * GMC Acadia support thanks to CryptoKylan!
+ * Decrease GPU power consumption
+ * NEOSv8 autoupdate
+
+Version 0.5.6 (2018-11-16)
+========================
+ * Refresh settings layout and add feature descriptions
+ * In Honda, keep stock camera on for logging and extra stock features; new openpilot giraffe setting is 0111!
+ * In Toyota, option to keep stock camera on for logging and extra stock features (e.g. AHB); 120Ohm resistor required on giraffe.
+ * Improve camera calibration stability
+ * More tuning to Honda positive accelerations
+ * Reduce brake pump use on Hondas
+ * Chevrolet Malibu support thanks to tylergets!
+ * Holden Astra support thanks to AlexHill!
+
+Version 0.5.5 (2018-10-20)
+========================
+ * Increase allowed Honda positive accelerations
+ * Fix sporadic unexpected braking when passing semi-trucks in Toyota
+ * Fix gear reading bug in Hyundai Elantra thanks to emmertex!
+
+Version 0.5.4 (2018-09-25)
+========================
+ * New Driving Model
+ * New Driver Monitoring Model
+ * Improve longitudinal mpc in mid-low speed braking
+ * Honda Accord hybrid support thanks to energee!
+ * Ship mpc binaries and sensibly reduce build time
+ * Calibration more stable
+ * More Hyundai and Kia cars supported thanks to emmertex!
+ * Various GM Volt improvements thanks to vntarasov!
+
+Version 0.5.3 (2018-09-03)
+========================
+ * Hyundai Santa Fe support!
+ * Honda Pilot 2019 support thanks to energee!
+ * Toyota Highlander support thanks to daehahn!
+ * Improve steering tuning for Honda Odyssey
+
+Version 0.5.2 (2018-08-16)
+========================
+ * New calibration: more accurate, a lot faster, open source!
+ * Enable orbd
+ * Add little endian support to CAN packer
+ * Fix fingerprint for Honda Accord 1.5T
+ * Improve driver monitoring model
+
+Version 0.5.1 (2018-08-01)
+========================
+ * Fix radar error on Civic sedan 2018
+ * Improve thermal management logic
+ * Alpha Toyota C-HR and Camry support!
+ * Auto-switch Driver Monitoring to 3 min counter when inaccurate
+
+Version 0.5 (2018-07-11)
+========================
+ * Driver Monitoring (beta) option in settings!
+ * Make visiond, loggerd and UI use less resources
+ * 60 FPS UI
+ * Better car parameters for most cars
+ * New sidebar with stats
+ * Remove Waze and Spotify to free up system resources
+ * Remove rear view mirror option
+ * Calibration 3x faster
+
+Version 0.4.7.2 (2018-06-25)
+==========================
+ * Fix loggerd lag issue
+ * No longer prompt for updates
+ * Mitigate right lane hugging for properly mounted EON (procedure on wiki)
+
+Version 0.4.7.1 (2018-06-18)
+==========================
+ * Fix Acura ILX steer faults
+ * Fix bug in mock car
+
+Version 0.4.7 (2018-06-15)
+==========================
+ * New model!
+ * GM Volt (and CT6 lateral) support!
+ * Honda Bosch lateral support!
+ * Improve actuator modeling to reduce lateral wobble
+ * Minor refactor of car abstraction layer
+ * Hack around orbd startup issue
+
+Version 0.4.6 (2018-05-18)
+==========================
+ * NEOSv6 required! Will autoupdate
+ * Stability improvements
+ * Fix all memory leaks
+ * Update C++ compiler to clang6
+ * Improve front camera exposure
+
+Version 0.4.5 (2018-04-27)
+==========================
+ * Release notes added to the update popup
+ * Improve auto shut-off logic to disallow empty battery
+ * Added onboarding instructions
+ * Include orbd, the first piece of new calibration algorithm
+ * Show remaining upload data instead of file numbers
+ * Fix UI bugs
+ * Fix memory leaks
+
+Version 0.4.4 (2018-04-13)
+==========================
+ * EON are flipped! Flip your EON's mount!
+ * Alpha Honda Ridgeline support thanks to energee!
+ * Support optional front camera recording
+ * Upload over cellular toggle now applies to all files, not just video
+ * Increase acceleration when closing lead gap
+ * User now prompted for future updates
+ * NEO no longer supported :(
+
+Version 0.4.3.2 (2018-03-29)
+============================
+ * Improve autofocus
+ * Improve driving when only one lane line is detected
+ * Added fingerprint for Toyota Corolla LE
+ * Fixed Toyota Corolla steer error
+ * Full-screen driving UI
+ * Improved path drawing
+
+Version 0.4.3.1 (2018-03-19)
+============================
+ * Improve autofocus
+ * Add check for MPC solution error
+ * Make first distracted warning visual only
+
+Version 0.4.3 (2018-03-13)
+==========================
+ * Add HDR and autofocus
+ * Update UI aesthetic
+ * Grey panda works in Waze
+ * Add alpha support for 2017 Honda Pilot
+ * Slight increase in acceleration response from stop
+ * Switch CAN sending to use CANPacker
+ * Fix pulsing acceleration regression on Honda
+ * Fix openpilot bugs when stock system is in use
+ * Change starting logic for chffrplus to use battery voltage
+
+Version 0.4.2 (2018-02-05)
+==========================
+ * Add alpha support for 2017 Lexus RX Hybrid
+ * Add alpha support for 2018 ACURA RDX
+ * Updated fingerprint to include Toyota Rav4 SE and Prius Prime
+ * Bugfixes for Acura ILX and Honda Odyssey
+
+Version 0.4.1 (2018-01-30)
+==========================
+ * Add alpha support for 2017 Toyota Corolla
+ * Add alpha support for 2018 Honda Odyssey with Honda Sensing
+ * Add alpha support for Grey Panda
+ * Refactored car abstraction layer to make car ports easier
+ * Increased steering torque limit on Honda CR-V by 30%
+
+Version 0.4.0.2 (2018-01-18)
+==========================
+ * Add focus adjustment slider
+ * Minor bugfixes
+
+Version 0.4.0.1 (2017-12-21)
+==========================
+ * New UI to match chffrplus
+ * Improved lateral control tuning to fix oscillations on Civic
+ * Add alpha support for 2017 Toyota Rav4 Hybrid
+ * Reduced CPU usage
+ * Removed unnecessary utilization of fan at max speed
+ * Minor bug fixes
+
+Version 0.3.9 (2017-11-21)
+==========================
+ * Add alpha support for 2017 Toyota Prius
+ * Improved longitudinal control using model predictive control
+ * Enable Forward Collision Warning
+ * Acura ILX now maintains openpilot engaged at standstill when brakes are applied
+
+Version 0.3.8.2 (2017-10-30)
+==========================
+ * Add alpha support for 2017 Toyota RAV4
+ * Smoother lateral control
+ * Stay silent if stock system is connected through giraffe
+ * Minor bug fixes
+
+Version 0.3.7 (2017-09-30)
+==========================
+ * Improved lateral control using model predictive control
+ * Improved lane centering
+ * Improved GPS
+ * Reduced tendency of path deviation near right side exits
+ * Enable engagement while the accelerator pedal is pressed
+ * Enable engagement while the brake pedal is pressed, when stationary and with lead vehicle within 5m
+ * Disable engagement when park brake or brake hold are active
+ * Fixed sporadic longitudinal pulsing in Civic
+ * Cleanups to vehicle interface
+
+Version 0.3.6.1 (2017-08-15)
+============================
+ * Mitigate low speed steering oscillations on some vehicles
+ * Include board steering check for CR-V
+
+Version 0.3.6 (2017-08-08)
+==========================
+ * Fix alpha CR-V support
+ * Improved GPS
+ * Fix display of target speed not always matching HUD
+ * Increased acceleration after stop
+ * Mitigated some vehicles driving too close to the right line
+
+Version 0.3.5 (2017-07-30)
+==========================
+ * Fix bug where new devices would not begin calibration
+ * Minor robustness improvements
+
+Version 0.3.4 (2017-07-28)
+==========================
+ * Improved model trained on more data
+ * Much improved controls tuning
+ * Performance improvements
+ * Bugfixes and improvements to calibration
+ * Driving log can play back video
+ * Acura only: system now stays engaged below 25mph as long as brakes are applied
+
+Version 0.3.3 (2017-06-28)
+===========================
+ * Improved model trained on more data
+ * Alpha CR-V support thanks to energee and johnnwvs!
+ * Using the opendbc project for DBC files
+ * Minor performance improvements
+ * UI update thanks to pjlao307
+ * Power off button
+ * 6% more torque on the Civic
+
+Version 0.3.2 (2017-05-22)
+===========================
+ * Minor stability bugfixes
+ * Added metrics and rear view mirror disable to settings
+ * Update model with more crowdsourced data
+
+Version 0.3.1 (2017-05-17)
+===========================
+ * visiond stability bugfix
+ * Add logging for angle and flashing
+
+Version 0.3.0 (2017-05-12)
+===========================
+ * Add CarParams struct to improve the abstraction layer
+ * Refactor visiond IPC to support multiple clients
+ * Add raw GPS and beginning support for navigation
+ * Improve model in visiond using crowdsourced data
+ * Add improved system logging to diagnose instability
+ * Rewrite baseui in React Native
+ * Moved calibration to the cloud
+
+Version 0.2.9 (2017-03-01)
+===========================
+ * Retain compatibility with NEOS v1
+
+Version 0.2.8 (2017-02-27)
+===========================
+ * Fix bug where frames were being dropped in minute 71
+
+Version 0.2.7 (2017-02-08)
+===========================
+ * Better performance and pictures at night
+ * Fix ptr alignment issue in boardd
+ * Fix brake error light, fix crash if too cold
+
+Version 0.2.6 (2017-01-31)
+===========================
+ * Fix bug in visiond model execution
+
+Version 0.2.5 (2017-01-30)
+===========================
+ * Fix race condition in manager
+
+Version 0.2.4 (2017-01-27)
+===========================
+ * OnePlus 3T support
+ * Enable installation as NEOS app
+ * Various minor bugfixes
+
+Version 0.2.3 (2017-01-11)
+===========================
+ * Reduce space usage by 80%
+ * Add better logging
+ * Add Travis CI
+
+Version 0.2.2 (2017-01-10)
+===========================
+ * Board triggers started signal on CAN messages
+ * Improved autoexposure
+ * Handle out of space, improve upload status
+
+Version 0.2.1 (2016-12-14)
+===========================
+ * Performance improvements, removal of more numpy
+ * Fix boardd process priority
+ * Make counter timer reset on use of steering wheel
+
+Version 0.2 (2016-12-12)
+=========================
+ * Car/Radar abstraction layers have shipped, see cereal/car.capnp
+ * controlsd has been refactored
+ * Shipped plant model and testing maneuvers
+ * visiond exits more gracefully now
+ * Hardware encoder in visiond should always init
+ * ui now turns off the screen after 30 seconds
+ * Switch to openpilot release branch for future releases
+ * Added preliminary Docker container to run tests on PC
+
+Version 0.1 (2016-11-29)
+=========================
+ * Initial release of openpilot
+ * Adaptive cruise control is working
+ * Lane keep assist is working
+ * Support for Acura ILX 2016 with AcuraWatch Plus
+ * Support for Honda Civic 2016 Touring Edition
diff --git a/SConstruct b/SConstruct
new file mode 100644
index 0000000..b04e390
--- /dev/null
+++ b/SConstruct
@@ -0,0 +1,410 @@
+import os
+import subprocess
+import sys
+import sysconfig
+import platform
+import numpy as np
+
+import SCons.Errors
+
+SCons.Warnings.warningAsException(True)
+
+# pending upstream fix - https://github.com/SCons/scons/issues/4461
+#SetOption('warn', 'all')
+
+TICI = os.path.isfile('/TICI')
+AGNOS = TICI
+
+Decider('MD5-timestamp')
+
+SetOption('num_jobs', int(os.cpu_count()/2))
+
+AddOption('--kaitai',
+ action='store_true',
+ help='Regenerate kaitai struct parsers')
+
+AddOption('--asan',
+ action='store_true',
+ help='turn on ASAN')
+
+AddOption('--ubsan',
+ action='store_true',
+ help='turn on UBSan')
+
+AddOption('--coverage',
+ action='store_true',
+ help='build with test coverage options')
+
+AddOption('--clazy',
+ action='store_true',
+ help='build with clazy')
+
+AddOption('--compile_db',
+ action='store_true',
+ help='build clang compilation database')
+
+AddOption('--ccflags',
+ action='store',
+ type='string',
+ default='',
+ help='pass arbitrary flags over the command line')
+
+AddOption('--snpe',
+ action='store_true',
+ help='use SNPE on PC')
+
+AddOption('--external-sconscript',
+ action='store',
+ metavar='FILE',
+ dest='external_sconscript',
+ help='add an external SConscript to the build')
+
+AddOption('--pc-thneed',
+ action='store_true',
+ dest='pc_thneed',
+ help='use thneed on pc')
+
+AddOption('--minimal',
+ action='store_false',
+ dest='extras',
+ default=os.path.islink(Dir('#rednose/').abspath), # minimal by default on release branch (where rednose is not a link)
+ help='the minimum build to run openpilot. no tests, tools, etc.')
+
+## Architecture name breakdown (arch)
+## - larch64: linux tici aarch64
+## - aarch64: linux pc aarch64
+## - x86_64: linux pc x64
+## - Darwin: mac x64 or arm64
+real_arch = arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
+if platform.system() == "Darwin":
+ arch = "Darwin"
+ brew_prefix = subprocess.check_output(['brew', '--prefix'], encoding='utf8').strip()
+elif arch == "aarch64" and AGNOS:
+ arch = "larch64"
+assert arch in ["larch64", "aarch64", "x86_64", "Darwin"]
+
+lenv = {
+ "PATH": os.environ['PATH'],
+ "LD_LIBRARY_PATH": [Dir(f"#third_party/acados/{arch}/lib").abspath],
+ "PYTHONPATH": Dir("#").abspath + ':' + Dir(f"#third_party/acados").abspath,
+
+ "ACADOS_SOURCE_DIR": Dir("#third_party/acados").abspath,
+ "ACADOS_PYTHON_INTERFACE_PATH": Dir("#third_party/acados/acados_template").abspath,
+ "TERA_PATH": Dir("#").abspath + f"/third_party/acados/{arch}/t_renderer"
+}
+
+rpath = lenv["LD_LIBRARY_PATH"].copy()
+
+if arch == "larch64":
+ lenv["LD_LIBRARY_PATH"] += ['/data/data/com.termux/files/usr/lib']
+
+ cpppath = [
+ "#third_party/opencl/include",
+ ]
+
+ libpath = [
+ "/usr/local/lib",
+ "/usr/lib",
+ "/system/vendor/lib64",
+ f"#third_party/acados/{arch}/lib",
+ ]
+
+ libpath += [
+ "#third_party/snpe/larch64",
+ "#third_party/libyuv/larch64/lib",
+ "/usr/lib/aarch64-linux-gnu"
+ ]
+ cflags = ["-DQCOM2", "-mcpu=cortex-a57"]
+ cxxflags = ["-DQCOM2", "-mcpu=cortex-a57"]
+ rpath += ["/usr/local/lib"]
+else:
+ cflags = []
+ cxxflags = []
+ cpppath = []
+ rpath += []
+
+ # MacOS
+ if arch == "Darwin":
+ libpath = [
+ f"#third_party/libyuv/{arch}/lib",
+ f"#third_party/acados/{arch}/lib",
+ f"{brew_prefix}/lib",
+ f"{brew_prefix}/opt/openssl@3.0/lib",
+ "/System/Library/Frameworks/OpenGL.framework/Libraries",
+ ]
+
+ cflags += ["-DGL_SILENCE_DEPRECATION"]
+ cxxflags += ["-DGL_SILENCE_DEPRECATION"]
+ cpppath += [
+ f"{brew_prefix}/include",
+ f"{brew_prefix}/opt/openssl@3.0/include",
+ ]
+ lenv["DYLD_LIBRARY_PATH"] = lenv["LD_LIBRARY_PATH"]
+ # Linux
+ else:
+ libpath = [
+ f"#third_party/acados/{arch}/lib",
+ f"#third_party/libyuv/{arch}/lib",
+ "/usr/lib",
+ "/usr/local/lib",
+ ]
+
+ if arch == "x86_64":
+ libpath += [
+ f"#third_party/snpe/{arch}"
+ ]
+ rpath += [
+ Dir(f"#third_party/snpe/{arch}").abspath,
+ ]
+
+if GetOption('asan'):
+ ccflags = ["-fsanitize=address", "-fno-omit-frame-pointer"]
+ ldflags = ["-fsanitize=address"]
+elif GetOption('ubsan'):
+ ccflags = ["-fsanitize=undefined"]
+ ldflags = ["-fsanitize=undefined"]
+else:
+ ccflags = []
+ ldflags = []
+
+# no --as-needed on mac linker
+if arch != "Darwin":
+ ldflags += ["-Wl,--as-needed", "-Wl,--no-undefined"]
+
+# Enable swaglog include in submodules
+cflags += ['-DSWAGLOG="\\"common/swaglog.h\\""']
+cxxflags += ['-DSWAGLOG="\\"common/swaglog.h\\""']
+
+ccflags_option = GetOption('ccflags')
+if ccflags_option:
+ ccflags += ccflags_option.split(' ')
+
+env = Environment(
+ ENV=lenv,
+ CCFLAGS=[
+ "-g",
+ "-fPIC",
+ "-O2",
+ "-Wunused",
+ "-Werror",
+ "-Wshadow",
+ "-Wno-unknown-warning-option",
+ "-Wno-deprecated-register",
+ "-Wno-register",
+ "-Wno-inconsistent-missing-override",
+ "-Wno-c99-designator",
+ "-Wno-reorder-init-list",
+ "-Wno-error=unused-but-set-variable",
+ ] + cflags + ccflags,
+
+ CPPPATH=cpppath + [
+ "#",
+ "#third_party/acados/include",
+ "#third_party/acados/include/blasfeo/include",
+ "#third_party/acados/include/hpipm/include",
+ "#third_party/catch2/include",
+ "#third_party/libyuv/include",
+ "#third_party/json11",
+ "#third_party/linux/include",
+ "#third_party/snpe/include",
+ "#third_party/qrcode",
+ "#third_party",
+ "#cereal",
+ "#opendbc/can",
+ "#third_party/maplibre-native-qt/include",
+ f"#third_party/maplibre-native-qt/{arch}/include"
+ ],
+
+ CC='clang',
+ CXX='clang++',
+ LINKFLAGS=ldflags,
+
+ RPATH=rpath,
+
+ CFLAGS=["-std=gnu11"] + cflags,
+ CXXFLAGS=["-std=c++1z"] + cxxflags,
+ LIBPATH=libpath + [
+ "#cereal",
+ "#third_party",
+ "#opendbc/can",
+ "#selfdrive/boardd",
+ "#common",
+ "#rednose/helpers",
+ ],
+ CYTHONCFILESUFFIX=".cpp",
+ COMPILATIONDB_USE_ABSPATH=True,
+ REDNOSE_ROOT="#",
+ tools=["default", "cython", "compilation_db", "rednose_filter"],
+ toolpath=["#rednose_repo/site_scons/site_tools"],
+)
+
+if arch == "Darwin":
+ # RPATH is not supported on macOS, instead use the linker flags
+ darwin_rpath_link_flags = [f"-Wl,-rpath,{path}" for path in env["RPATH"]]
+ env["LINKFLAGS"] += darwin_rpath_link_flags
+
+if GetOption('compile_db'):
+ env.CompilationDatabase('compile_commands.json')
+
+# Setup cache dir
+cache_dir = '/data/scons_cache' if AGNOS else '/tmp/scons_cache'
+CacheDir(cache_dir)
+Clean(["."], cache_dir)
+
+node_interval = 5
+node_count = 0
+def progress_function(node):
+ global node_count
+ node_count += node_interval
+ sys.stderr.write("progress: %d\n" % node_count)
+
+if os.environ.get('SCONS_PROGRESS'):
+ Progress(progress_function, interval=node_interval)
+
+# Cython build environment
+py_include = sysconfig.get_paths()['include']
+envCython = env.Clone()
+envCython["CPPPATH"] += [py_include, np.get_include()]
+envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-shadow", "-Wno-deprecated-declarations"]
+envCython["CCFLAGS"].remove("-Werror")
+
+envCython["LIBS"] = []
+if arch == "Darwin":
+ envCython["LINKFLAGS"] = ["-bundle", "-undefined", "dynamic_lookup"] + darwin_rpath_link_flags
+else:
+ envCython["LINKFLAGS"] = ["-pthread", "-shared"]
+
+Export('envCython')
+
+# Qt build environment
+qt_env = env.Clone()
+qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "Multimedia", "Quick", "Qml", "QuickWidgets", "Location", "Positioning", "DBus", "Xml"]
+
+qt_libs = []
+if arch == "Darwin":
+ qt_env['QTDIR'] = f"{brew_prefix}/opt/qt@5"
+ qt_dirs = [
+ os.path.join(qt_env['QTDIR'], "include"),
+ ]
+ qt_dirs += [f"{qt_env['QTDIR']}/include/Qt{m}" for m in qt_modules]
+ qt_env["LINKFLAGS"] += ["-F" + os.path.join(qt_env['QTDIR'], "lib")]
+ qt_env["FRAMEWORKS"] += [f"Qt{m}" for m in qt_modules] + ["OpenGL"]
+ qt_env.AppendENVPath('PATH', os.path.join(qt_env['QTDIR'], "bin"))
+else:
+ qt_install_prefix = subprocess.check_output(['qmake', '-query', 'QT_INSTALL_PREFIX'], encoding='utf8').strip()
+ qt_install_headers = subprocess.check_output(['qmake', '-query', 'QT_INSTALL_HEADERS'], encoding='utf8').strip()
+
+ qt_env['QTDIR'] = qt_install_prefix
+ qt_dirs = [
+ f"{qt_install_headers}",
+ ]
+
+ qt_gui_path = os.path.join(qt_install_headers, "QtGui")
+ qt_gui_dirs = [d for d in os.listdir(qt_gui_path) if os.path.isdir(os.path.join(qt_gui_path, d))]
+ qt_dirs += [f"{qt_install_headers}/QtGui/{qt_gui_dirs[0]}/QtGui", ] if qt_gui_dirs else []
+ qt_dirs += [f"{qt_install_headers}/Qt{m}" for m in qt_modules]
+
+ qt_libs = [f"Qt5{m}" for m in qt_modules]
+ if arch == "larch64":
+ qt_libs += ["GLESv2", "wayland-client"]
+ qt_env.PrependENVPath('PATH', Dir("#third_party/qt5/larch64/bin/").abspath)
+ elif arch != "Darwin":
+ qt_libs += ["GL"]
+qt_env['QT3DIR'] = qt_env['QTDIR']
+
+# compatibility for older SCons versions
+try:
+ qt_env.Tool('qt3')
+except SCons.Errors.UserError:
+ qt_env.Tool('qt')
+
+qt_env['CPPPATH'] += qt_dirs# + ["#selfdrive/ui/qt/"]
+qt_flags = [
+ "-D_REENTRANT",
+ "-DQT_NO_DEBUG",
+ "-DQT_WIDGETS_LIB",
+ "-DQT_GUI_LIB",
+ "-DQT_QUICK_LIB",
+ "-DQT_QUICKWIDGETS_LIB",
+ "-DQT_QML_LIB",
+ "-DQT_CORE_LIB",
+ "-DQT_MESSAGELOGCONTEXT",
+]
+qt_env['CXXFLAGS'] += qt_flags
+qt_env['LIBPATH'] += ['#selfdrive/ui', f"#third_party/maplibre-native-qt/{arch}/lib"]
+qt_env['RPATH'] += [Dir(f"#third_party/maplibre-native-qt/{arch}/lib").srcnode().abspath]
+qt_env['LIBS'] = qt_libs
+
+if GetOption("clazy"):
+ checks = [
+ "level0",
+ "level1",
+ "no-range-loop",
+ "no-non-pod-global-static",
+ ]
+ qt_env['CXX'] = 'clazy'
+ qt_env['ENV']['CLAZY_IGNORE_DIRS'] = qt_dirs[0]
+ qt_env['ENV']['CLAZY_CHECKS'] = ','.join(checks)
+
+Export('env', 'qt_env', 'arch', 'real_arch')
+
+# Build common module
+SConscript(['common/SConscript'])
+Import('_common', '_gpucommon')
+
+common = [_common, 'json11']
+gpucommon = [_gpucommon]
+
+Export('common', 'gpucommon')
+
+# Build cereal and messaging
+SConscript(['cereal/SConscript'])
+
+cereal = [File('#cereal/libcereal.a')]
+messaging = [File('#cereal/libmessaging.a')]
+visionipc = [File('#cereal/libvisionipc.a')]
+messaging_python = [File('#cereal/messaging/messaging_pyx.so')]
+
+Export('cereal', 'messaging', 'messaging_python', 'visionipc')
+
+# Build other submodules
+SConscript([
+ 'body/board/SConscript',
+ 'opendbc/can/SConscript',
+ 'panda/SConscript',
+])
+
+# Build rednose library
+SConscript(['rednose/SConscript'])
+
+# Build system services
+SConscript([
+ 'system/proclogd/SConscript',
+ 'system/ubloxd/SConscript',
+ 'system/loggerd/SConscript',
+])
+if arch != "Darwin":
+ SConscript([
+ 'system/camerad/SConscript',
+ 'system/sensord/SConscript',
+ 'system/logcatd/SConscript',
+ ])
+
+# Build openpilot
+SConscript(['third_party/SConscript'])
+
+SConscript(['selfdrive/boardd/SConscript'])
+SConscript(['selfdrive/controls/lib/lateral_mpc_lib/SConscript'])
+SConscript(['selfdrive/controls/lib/longitudinal_mpc_lib/SConscript'])
+SConscript(['selfdrive/locationd/SConscript'])
+SConscript(['selfdrive/navd/SConscript'])
+SConscript(['selfdrive/modeld/SConscript'])
+SConscript(['selfdrive/ui/SConscript'])
+
+if arch in ['x86_64', 'aarch64', 'Darwin'] and Dir('#tools/cabana/').exists() and GetOption('extras'):
+ SConscript(['tools/replay/SConscript'])
+ SConscript(['tools/cabana/SConscript'])
+
+external_sconscript = GetOption('external_sconscript')
+if external_sconscript:
+ SConscript([external_sconscript])
diff --git a/body/.gitignore b/body/.gitignore
new file mode 100644
index 0000000..cd74bc6
--- /dev/null
+++ b/body/.gitignore
@@ -0,0 +1,15 @@
+*.pyc
+.*.swp
+.*.swo
+*.o
+*.so
+*.os
+*.d
+*.dump
+a.out
+*~
+.#*
+.vscode*
+.DS_Store
+board/obj/
+.sconsign.dblite
diff --git a/body/board/SConscript b/body/board/SConscript
new file mode 100644
index 0000000..39927c8
--- /dev/null
+++ b/body/board/SConscript
@@ -0,0 +1,197 @@
+import os
+import subprocess
+
+PREFIX = "arm-none-eabi-"
+BUILDER = "DEV"
+
+common_flags = []
+build_projects = {}
+
+build_projects["body"] = {
+ "MAIN": "main.c",
+ "STARTUP_FILE": "startup_stm32f413xx.s",
+ "LINKER_SCRIPT": "stm32fx_flash.ld",
+ "APP_START_ADDRESS": "0x08004000",
+ "PROJECT_FLAGS": [
+ "-mcpu=cortex-m4",
+ "-mhard-float",
+ "-DSTM32F4",
+ "-DSTM32F413xx",
+ "-mfpu=fpv4-sp-d16",
+ "-fsingle-precision-constant",
+ "-Os",
+ "-g",
+ ],
+}
+
+if os.getenv("RELEASE"):
+ BUILD_TYPE = "RELEASE"
+ cert_fn = os.getenv("CERT")
+ assert cert_fn is not None, 'No certificate file specified. Please set CERT env variable'
+ assert os.path.exists(cert_fn), 'Certificate file not found. Please specify absolute path'
+else:
+ BUILD_TYPE = "DEBUG"
+ cert_fn = File("../certs/debug").srcnode().relpath
+ common_flags += ["-DALLOW_DEBUG"]
+
+if os.getenv("DEBUG"):
+ common_flags += ["-DDEBUG"]
+
+includes = [
+ "inc/STM32F4xx_HAL_Driver/Inc",
+ "inc",
+ "..",
+ ".",
+]
+
+c_sources = [
+ ["hal_flash", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c"],
+ ["hal_pwr", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c"],
+ ["hal_rcc", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c"],
+ ["hal_i2c", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c"],
+ ["hal_i2c_ex", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c"],
+ ["hal_tim", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c"],
+ ["hal_tim_ex", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c"],
+ ["hal_adc_ex", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c"],
+ ["hal_cortex", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c"],
+ ["hal_flash_ex", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c"],
+ ["hal_gpio", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c"],
+ ["hal_rcc_ex", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c"],
+ ["hal", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c"],
+ ["hal_adc", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c"],
+ ["hal_dma", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c"],
+ ["system", "inc/system_stm32f4xx.c"],
+ ["it", "inc/stm32f4xx_it.c"],
+ ["bldc", "bldc/bldc.c"],
+ ["bldc_data", "bldc/BLDC_controller_data.c"],
+ ["bldc_con", "bldc/BLDC_controller.c"],
+ ["util", "util.c"],
+]
+
+c_bstub_sources = [
+ ["hal_pwr", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c"],
+ ["hal_rcc", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c"],
+ ["hal_cortex", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c"],
+ ["hal_gpio", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c"],
+ ["hal_rcc_ex", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c"],
+ ["hal", "inc/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c"],
+ ["system", "inc/system_stm32f4xx.c"],
+ ["it", "inc/stm32f4xx_it.c"],
+ ["util", "util.c"],
+]
+
+def get_version(builder, build_type):
+ try:
+ git = subprocess.check_output(["git", "rev-parse", "--short=8", "HEAD"], encoding='utf8').strip()
+ except subprocess.CalledProcessError:
+ git = "00000000"
+ return f"{git}"
+
+
+def to_c_uint32(x):
+ nums = []
+ for _ in range(0x20):
+ nums.append(x % (2**32))
+ x //= (2**32)
+ return "{" + 'U,'.join(map(str, nums)) + "U}"
+
+
+def get_key_header(name):
+ from Crypto.PublicKey import RSA
+
+ public_fn = f'../certs/{name}.pub'
+ rsa = RSA.importKey(open(public_fn).read())
+ assert(rsa.size_in_bits() == 1024)
+
+ rr = pow(2**1024, 2, rsa.n)
+ n0inv = 2**32 - pow(rsa.n, -1, 2**32)
+
+ r = [
+ f"RSAPublicKey {name}_rsa_key = {{",
+ f" .len = 0x20,",
+ f" .n0inv = {n0inv}U,",
+ f" .n = {to_c_uint32(rsa.n)},",
+ f" .rr = {to_c_uint32(rr)},",
+ f" .exponent = {rsa.e},",
+ f"}};",
+ ]
+ return r
+
+def objcopy(source, target, env, for_signature):
+ return '$OBJCOPY -O binary %s %s' % (source[0], target[0])
+
+# Common autogenerated includes
+git_ver = get_version(BUILDER, BUILD_TYPE)
+with open("obj/gitversion.h", "w") as f:
+ f.write(f'const uint8_t gitversion[8] = "{git_ver}";\n')
+
+certs = [get_key_header(n) for n in ["debug", "release"]]
+with open("obj/cert.h", "w") as f:
+ for cert in certs:
+ f.write("\n".join(cert) + "\n")
+
+for project_name in build_projects:
+ project = build_projects[project_name]
+ linkerscript_fn = File(project["LINKER_SCRIPT"]).srcnode().relpath
+
+ flags = [
+ "-Wall",
+ "-Wextra",
+ "-Wstrict-prototypes",
+ "-Werror",
+ "-mlittle-endian",
+ "-mthumb",
+ "-nostdlib",
+ "-fno-builtin",
+ f"-T{linkerscript_fn}",
+ "-std=gnu11",
+ "-fdata-sections",
+ "-ffunction-sections",
+ "-Wl,--gc-sections",
+ ] + project["PROJECT_FLAGS"] + common_flags
+
+ project_env = Environment(
+ ENV=os.environ,
+ CC=PREFIX + 'gcc',
+ AS=PREFIX + 'gcc',
+ OBJCOPY=PREFIX + 'objcopy',
+ OBJDUMP=PREFIX + 'objdump',
+ ASCOM="$AS $ASFLAGS -o $TARGET -c $SOURCES",
+ CFLAGS=flags,
+ ASFLAGS=flags,
+ LINKFLAGS=flags,
+ LIBS = ['gcc',],
+ CPPPATH=includes,
+ BUILDERS={
+ 'Objcopy': Builder(generator=objcopy, suffix='.bin', src_suffix='.elf')
+ }
+ )
+ startup = project_env.Object(project["STARTUP_FILE"])
+
+ c_bstub_obj_list = []
+ for c in c_bstub_sources:
+ c_bstub_obj_list.append(project_env.Object(f"{c[0]}-{project_name}", c[1]))
+
+ # Bootstub
+ crypto_obj = [
+ project_env.Object(f"rsa-{project_name}", "../crypto/rsa.c"),
+ project_env.Object(f"sha-{project_name}", "../crypto/sha.c")
+ ]
+ bootstub_obj = project_env.Object(f"bootstub-{project_name}", "bootstub.c")
+ bootstub_elf = project_env.Program(f"obj/bootstub.{project_name}.elf", [startup] + crypto_obj + c_bstub_obj_list + [bootstub_obj])
+ bootstub_bin = project_env.Objcopy(f"obj/bootstub.{project_name}.bin", bootstub_elf)
+
+ c_obj_list = []
+ for c in c_sources:
+ c_obj_list.append(project_env.Object(f"{c[0]}-{project_name}", c[1]))
+
+ # Build main
+ main_obj = project_env.Object(f"main-{project_name}", project["MAIN"])
+ obj_list = [startup, main_obj] + c_obj_list
+ main_elf = project_env.Program(f"obj/{project_name}.elf", obj_list,
+ LINKFLAGS=[f"-Wl,--section-start,.isr_vector={project['APP_START_ADDRESS']}"] + flags)
+ main_bin = project_env.Objcopy(f"obj/{project_name}.bin", main_elf)
+
+ # Sign main
+ sign_py = File("../crypto/sign.py").srcnode().relpath
+ panda_bin_signed = project_env.Command(f"obj/{project_name}.bin.signed", main_bin, f"SETLEN=1 {sign_py} $SOURCE $TARGET {cert_fn}")
diff --git a/body/board/bldc/BLDC_controller.c b/body/board/bldc/BLDC_controller.c
new file mode 100644
index 0000000..ae63bd4
--- /dev/null
+++ b/body/board/bldc/BLDC_controller.c
@@ -0,0 +1,3376 @@
+/*
+ * File: BLDC_controller.c
+ *
+ * Code generated for Simulink model 'BLDC_controller'.
+ *
+ * Model version : 1.1297
+ * Simulink Coder version : 8.13 (R2017b) 24-Jul-2017
+ * C/C++ source code generated on : Sun Mar 6 11:02:11 2022
+ *
+ * Target selection: ert.tlc
+ * Embedded hardware selection: ARM Compatible->ARM Cortex
+ * Emulation hardware selection:
+ * Differs from embedded hardware (MATLAB Host)
+ * Code generation objectives:
+ * 1. Execution efficiency
+ * 2. RAM efficiency
+ * Validation result: Not run
+ */
+
+#include "BLDC_controller.h"
+
+/* Named constants for Chart: '