mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-07-08 14:22:05 +08:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 79bb0dc1bd | |||
| 15e48feea9 | |||
| 5de1d94a15 | |||
| 2d5c9760ac | |||
| 2ed5c92830 | |||
| bdb733ddc9 | |||
| b63ef7b0bf | |||
| 09d1604b84 | |||
| 61f7690265 | |||
| 4cb7263dd6 | |||
| ef2331b5df | |||
| 9be3925ee1 | |||
| 8d760272c7 | |||
| 22e0b4d597 | |||
| 08afbd7cb5 | |||
| f311c8b1d7 | |||
| fb7076a042 | |||
| cd0ee08763 | |||
| f7ab369d47 | |||
| 54d5281064 | |||
| fa3a0ba747 | |||
| b3926faebb | |||
| 9810b10c49 |
@@ -0,0 +1,97 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master", "*-c3", "master*" ]
|
||||
pull_request:
|
||||
branches: [ "master", "*-c3", "master*" ]
|
||||
schedule:
|
||||
- cron: '39 7 * * 2'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze (${{ matrix.language }})
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
# required to fetch internal or private CodeQL packs
|
||||
packages: read
|
||||
|
||||
# only required for workflows in private repositories
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- language: c-cpp
|
||||
build-mode: autobuild
|
||||
- language: javascript-typescript
|
||||
build-mode: none
|
||||
- language: python
|
||||
build-mode: none
|
||||
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
|
||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
||||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
||||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
||||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# If the analyze step fails for one of the languages you are analyzing with
|
||||
# "We were unable to automatically build your code", modify the matrix above
|
||||
# to set the build mode to "manual" for that language. Then modify this step
|
||||
# to build your code.
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
- if: matrix.build-mode == 'manual'
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'If you are using a "manual" build mode for one or more of the' \
|
||||
'languages you are analyzing, replace this with the commands to build' \
|
||||
'your code, for example:'
|
||||
echo ' make bootstrap'
|
||||
echo ' make release'
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
@@ -0,0 +1,55 @@
|
||||
name: Mirror to GitLab
|
||||
|
||||
on:
|
||||
push:
|
||||
delete:
|
||||
workflow_dispatch: # This enables manual triggering
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Wait for other instances of this workflow to conclude
|
||||
uses: softprops/turnstyle@8db075d65b19bf94e6e8687b504db69938dc3c65
|
||||
with:
|
||||
same-branch-only: 'true'
|
||||
abort-after-seconds: 300
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
fetch-depth: 0 # Fetch full history
|
||||
|
||||
- name: Set up Git
|
||||
run: |
|
||||
git config --global user.name 'GitHub Action'
|
||||
git config --global user.email 'action@github.com'
|
||||
|
||||
- name: Set up SSH
|
||||
uses: webfactory/ssh-agent@v0.5.3
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
||||
- name: Add GitLab public keys
|
||||
run: |
|
||||
ssh-keyscan -H gitlab.com >> ~/.ssh/known_hosts
|
||||
|
||||
- name: Sync and commit changes
|
||||
id: sync-and-commit
|
||||
run: |
|
||||
git lfs pull
|
||||
|
||||
# Add GitLab remote
|
||||
git remote add gitlab git@gitlab.com:sunnypilot/sunnyhaibin/sunnypilot-github-mirror.git
|
||||
|
||||
# Fetch from GitLab and check if the branch exists
|
||||
if git fetch gitlab ${{ github.ref }}; then
|
||||
# Merge changes from GitLab if the branch exists
|
||||
git merge gitlab/${{ github.ref_name }} --allow-unrelated-histories --strategy-option=theirs
|
||||
else
|
||||
echo "Branch does not exist on GitLab, skipping merge."
|
||||
fi
|
||||
git push -u gitlab ${{ github.ref }} # If you have issues with "push rejected missing LFS" or something. Make sure you disabled LFS on the GITLAB repo if you intend to use a different LFS repo other than the target repo
|
||||
+29
-47
@@ -9,6 +9,10 @@ variables:
|
||||
GIT_CONFIG_USER_EMAIL: "gitlab@pipeline.com"
|
||||
GIT_CONFIG_USER_NAME: "Gitlab Pipeline"
|
||||
PUBLIC_REPO_URL: "https://github.com/sunnyhaibin/sunnypilot"
|
||||
BASE_BUILD_NUMER: 3000
|
||||
|
||||
EXTRA_VERSION_IDENTIFIER: "${CI_PIPELINE_IID}"
|
||||
NEW_BRANCH: ${CI_COMMIT_REF_NAME}-prebuilt
|
||||
|
||||
stages:
|
||||
- build
|
||||
@@ -23,7 +27,8 @@ default:
|
||||
- x86
|
||||
|
||||
.default_before_script: &default_before_script
|
||||
- 'export VERSION=$(eval $VERSION)${EXTRA_VERSION_IDENTIFIER}'
|
||||
- 'if [ "$EXTRA_VERSION_IDENTIFIER" = "$CI_PIPELINE_IID" ]; then export EXTRA_VERSION_IDENTIFIER=$((CI_PIPELINE_IID + BASE_BUILD_NUMER)); fi'
|
||||
- 'export VERSION=$(eval $VERSION)-${EXTRA_VERSION_IDENTIFIER}'
|
||||
- 'mkdir -p "${BUILD_DIR}/"'
|
||||
- 'git config --global user.email "${GIT_CONFIG_USER_EMAIL}"'
|
||||
- 'git config --global user.name "${GIT_CONFIG_USER_NAME}"'
|
||||
@@ -34,33 +39,31 @@ workflow: # If running on any branch other than main.
|
||||
# We are an MR, but it's a draft, we won't proceed with anything.
|
||||
- if: '$CI_MERGE_REQUEST_TITLE =~ /^wip:/i || $CI_MERGE_REQUEST_TITLE =~ /^draft:/i'
|
||||
when: never
|
||||
# We are a merge request
|
||||
- if: $CI_MERGE_REQUEST_IID
|
||||
variables:
|
||||
EXTRA_VERSION_IDENTIFIER: "-${CI_PIPELINE_IID}"
|
||||
NEW_BRANCH: ${CI_COMMIT_REF_NAME}-prebuilt
|
||||
when: always
|
||||
|
||||
# Below are the rules when a commit is done (code has been added to the branch)
|
||||
# Commit to master-dev-c3
|
||||
- if: $CI_COMMIT_REF_NAME == $DEV_C3_SOURCE_BRANCH
|
||||
variables:
|
||||
EXTRA_VERSION_IDENTIFIER: "-${CI_PIPELINE_IID}"
|
||||
EXTRA_VERSION_IDENTIFIER: "${CI_PIPELINE_IID}"
|
||||
NEW_BRANCH: "dev-c3"
|
||||
AUTO_BUILD: true
|
||||
when: always
|
||||
#commit made to main (master)
|
||||
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
|
||||
variables:
|
||||
NEW_BRANCH: "staging-c3"
|
||||
VERSION: 'cat common/version.h | grep COMMA_VERSION | sed -e "s/[^0-9|.]//g"'
|
||||
EXTRA_VERSION_IDENTIFIER: "-staging"
|
||||
EXTRA_VERSION_IDENTIFIER: "staging"
|
||||
AUTO_PUBLISH: true
|
||||
AUTO_BUILD: true
|
||||
when: always
|
||||
# if tag
|
||||
- if: $CI_COMMIT_TAG
|
||||
variables:
|
||||
NEW_BRANCH: "release-c3"
|
||||
VERSION: 'cat common/version.h | grep COMMA_VERSION | sed -e "s/[^0-9|.]//g"'
|
||||
EXTRA_VERSION_IDENTIFIER: "-release"
|
||||
EXTRA_VERSION_IDENTIFIER: "release"
|
||||
AUTO_BUILD: true
|
||||
- when: always
|
||||
|
||||
|
||||
@@ -92,7 +95,7 @@ build:
|
||||
- sed -i '/from .board.jungle import PandaJungle, PandaJungleDFU/s/^/#/' panda/__init__.py # comment panda jungle when prebuilt
|
||||
- scons -j$(nproc) cache_dir=${CI_DIR}/scons_cache --minimal
|
||||
- touch ${BUILD_DIR}/prebuilt
|
||||
- sudo rm -rf ${OUTPUT_DIR}
|
||||
- sudo rm -rf ${OUTPUT_DIR}
|
||||
- mkdir -p ${OUTPUT_DIR}
|
||||
# We first include the paths we want to keep, even if we later will be excluding the other things on those paths
|
||||
- rsync -avm
|
||||
@@ -135,39 +138,16 @@ build:
|
||||
--chown=comma:comma
|
||||
${BUILD_DIR}/ ${OUTPUT_DIR}/
|
||||
after_script:
|
||||
# cleanup build dir after doing work
|
||||
# cleanup build dir after doing work
|
||||
- find $BUILD_DIR/ -mindepth 1 -delete
|
||||
artifacts:
|
||||
paths:
|
||||
- ${OUTPUT_DIR}/
|
||||
tags: [ 'sunnypilot', 'tici' ]
|
||||
rules:
|
||||
- if: $CI_MERGE_REQUEST_IID
|
||||
when: manual
|
||||
- if: $NEW_BRANCH
|
||||
- if: $AUTO_BUILD
|
||||
when: always
|
||||
|
||||
check no source code sent:
|
||||
image: alpine
|
||||
stage: sanity
|
||||
variables:
|
||||
FORBIDDEN_FILE_EXTENSIONS: "*.a,*.o,*.os,*.pyc,moc_*,*.cc,Jenkinsfile,supercombo.onnx,.sconsign.dblite"
|
||||
FORBIDDEN_DIR_PATTERNS: "*panda/certs,*panda/crypto,*release,*.github,*selfdrive/ui/replay,*__pycache__"
|
||||
REQUIRED_FILE_EXTENSIONS: "*.py,*.json"
|
||||
REQUIRED_DIR_PATTERNS: "*selfdrive/ui,*openpilot"
|
||||
before_script:
|
||||
- apk update && apk upgrade
|
||||
- apk add bash findutils
|
||||
script:
|
||||
- cd ${OUTPUT_DIR}
|
||||
- echo "Checking that we have properly cleaned up"
|
||||
- ${CI_DIR}/sanity_check.sh "$FORBIDDEN_FILE_EXTENSIONS" "$FORBIDDEN_DIR_PATTERNS" true
|
||||
- echo "Checking that our sanity check works and also checking that some required files are indeed found"
|
||||
- ${CI_DIR}/sanity_check.sh "$REQUIRED_FILE_EXTENSIONS" "$REQUIRED_DIR_PATTERNS" false
|
||||
rules:
|
||||
- if: $NEW_BRANCH
|
||||
when: on_success
|
||||
- when: never
|
||||
- when: manual
|
||||
|
||||
.publish_base: &publish_base
|
||||
image: alpine
|
||||
@@ -177,9 +157,6 @@ check no source code sent:
|
||||
needs:
|
||||
- job: build
|
||||
artifacts: true
|
||||
- job: "check no source code sent"
|
||||
artifacts: false
|
||||
optional: false
|
||||
before_script:
|
||||
- 'apk update && apk upgrade'
|
||||
- 'apk add git bash openssh'
|
||||
@@ -196,17 +173,19 @@ check no source code sent:
|
||||
- echo "${GIT_ORIGIN}"
|
||||
- echo "Calling to publish [${CI_DIR}/publish.sh ${CI_PROJECT_DIR} ${OUTPUT_DIR} ${NEW_BRANCH} ${VERSION} ${GIT_ORIGIN}]"
|
||||
- git config --global --add safe.directory ${OUTPUT_DIR}
|
||||
- $CI_DIR/publish.sh "${CI_PROJECT_DIR}" "${OUTPUT_DIR}" "${NEW_BRANCH}" "${VERSION}" "${GIT_ORIGIN}" "${EXTRA_VERSION_IDENTIFIER}"
|
||||
- $CI_DIR/publish.sh "${CI_PROJECT_DIR}" "${OUTPUT_DIR}" "${NEW_BRANCH}" "${VERSION}" "${GIT_ORIGIN}" "-${EXTRA_VERSION_IDENTIFIER}"
|
||||
allow_failure: false
|
||||
|
||||
publish to private gitlab prebuilt:
|
||||
extends: ".publish_base"
|
||||
variables:
|
||||
GIT_ORIGIN: git@gitlab.com:sunnypilot/public/sunnypilot.git
|
||||
GIT_ORIGIN: git@gitlab.com:sunnypilot/public/sunnypilot-prebuilts.git
|
||||
rules:
|
||||
- if: $NEW_BRANCH
|
||||
- if: $AUTO_BUILD
|
||||
when: on_success
|
||||
- when: never
|
||||
- if: $CI_MERGE_REQUEST_IID
|
||||
when: on_success
|
||||
- when: manual
|
||||
|
||||
publish to public github prebuilt:
|
||||
extends: ".publish_base"
|
||||
@@ -215,9 +194,9 @@ publish to public github prebuilt:
|
||||
GIT_CONFIG_USER_EMAIL: "jason.wen@sunnypilot.ai"
|
||||
GIT_CONFIG_USER_NAME: "Jason Wen"
|
||||
rules:
|
||||
- if: $NEW_BRANCH
|
||||
when: manual
|
||||
- when: never
|
||||
- if: $AUTO_PUBLISH
|
||||
when: on_success
|
||||
- when: manual
|
||||
|
||||
.notify_discord: ¬ify_discord
|
||||
image: alpine
|
||||
@@ -251,6 +230,9 @@ notify new dev build:
|
||||
needs: ["publish to public github prebuilt"] # This notify shall only happen after a publish to github public
|
||||
variables:
|
||||
TEMPLATE: "discord_template_notify_dev_public.json"
|
||||
before_script:
|
||||
- !reference [".notify_discord", "before_script"]
|
||||
- export EXTRA_VERSION_IDENTIFIER=$((CI_PIPELINE_IID + BASE_BUILD_NUMER))
|
||||
rules:
|
||||
- if: $NEW_BRANCH == "dev-c3"
|
||||
variables:
|
||||
|
||||
@@ -170,16 +170,16 @@ After running the command to install the desired branch, your comma device shoul
|
||||
* Speed Limit Control (SLC) - Set speed limit based on map data or car interface (if applicable)
|
||||
* HKG only: Highway Driving Assist (HDA) status integration - Use cars native speed sign detection to set desired speed (on applicable HKG cars only)
|
||||
- [**Gap Adjust Cruise (GAC)**](#gap-adjust-cruise) - Allow `GAP`/`INTERVAL`/`DISTANCE` button on the steering wheel or on-screen button to adjust the follow distance from the lead car. See table below for options
|
||||
- [**Quiet Drive 🤫**](#-quiet-drive) - Toggle to mute all notification sounds (excluding driver safety warnings)
|
||||
- [**Auto Lane Change Timer**](#Auto-Lane-Change-Timer) - Set a timer to delay the auto lane change operation when the blinker is used. No nudge on the steering wheel is required to auto lane change if a timer is set
|
||||
- [**Force Car Recognition (FCR)**](#Force-Car-Recognition-) - Use a selector to force your car to be recognized by sunnypilot
|
||||
- [**Fix sunnypilot No Offroad**](#Fix-sunnypilot-No-Offroad) - Enforce sunnypilot to go offroad and turns off after shutting down the car. This feature fixes non-official devices running sunnypilot without comma power
|
||||
- [**Enable ACC+MADS with RES+/SET-**](#Enable-ACC+MADS-with-RES+/SET-) - Engage both ACC and MADS with a single press of RES+ or SET- button
|
||||
- [**Offline OSM Maps**](#Offline-OSM-Maps) - OSM database can now be downloaded locally for offline use[^2]. This enables offline SLC, V-TSC and M-TSC. Currently available for US South, US West, US Northeast, Florida, Taiwan, South Africa and New Zealand
|
||||
- [**Various Live Tuning**](#Various-Live-Tuning) - Ability to tailor your driving experience on the fly:
|
||||
* Enforce Torque Lateral Control - Use the newest [torque controller](https://blog.comma.ai/0815release/#torque-controller) for all vehicles.
|
||||
* Torque Lateral Control Live Tune - Ability to adjust the torque controller’s `FRICTION` and `LAT_ACCEL_FACTOR` values to suit your vehicle.
|
||||
* Torque Lateral Controller Self-Tune - Enable automatic turning for the Torque controller.
|
||||
- [**Quiet Drive 🤫**](#-quiet-drive) - Toggle to mute all notification sounds (excluding driver safety warnings)
|
||||
- [**Auto Lane Change Timer**](#Auto-Lane-Change-Timer) - Set a timer to delay the auto lane change operation when the blinker is used. No nudge on the steering wheel is required to auto lane change if a timer is set
|
||||
- [**Force Car Recognition (FCR)**](#Force-Car-Recognition-) - Use a selector to force your car to be recognized by sunnypilot
|
||||
- [**Fix sunnypilot No Offroad**](#Fix-sunnypilot-No-Offroad) - Enforce sunnypilot to go offroad and turns off after shutting down the car. This feature fixes non-official devices running sunnypilot without comma power
|
||||
- [**Enable ACC+MADS with RES+/SET-**](#Enable-ACC+MADS-with-RES+/SET-) - Engage both ACC and MADS with a single press of RES+ or SET- button
|
||||
- [**Offline OSM Maps**](#Offline-OSM-Maps) - OSM database can now be downloaded locally for offline use[^2]. This enables offline SLC, V-TSC and M-TSC. Currently available for US South, US West, US Northeast, Florida, Taiwan, South Africa and New Zealand
|
||||
- [**Various Live Tuning**](#Various-Live-Tuning) - Ability to tailor your driving experience on the fly:
|
||||
* Enforce Torque Lateral Control - Use the newest [torque controller](https://blog.comma.ai/0815release/#torque-controller) for all vehicles.
|
||||
* Torque Lateral Control Live Tune - Ability to adjust the torque controller’s `FRICTION` and `LAT_ACCEL_FACTOR` values to suit your vehicle.
|
||||
* Torque Lateral Controller Self-Tune - Enable automatic turning for the Torque controller.
|
||||
|
||||
### Visual Enhancements
|
||||
* **M.A.D.S Status Icon** - Dedicated icon to display M.A.D.S. engagement status
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"embeds": [
|
||||
{
|
||||
"title": "🎉 sunnypilot `${NEW_BRANCH}` New Update 🎉",
|
||||
"description": "[sunnypilot](${PUBLIC_REPO_URL}): Build #${CI_PIPELINE_IID} of branch [${NEW_BRANCH}](${PUBLIC_REPO_URL}/tree/${NEW_BRANCH}) has been published.\n\nDrive safe! 🚗💨",
|
||||
"description": "[sunnypilot](${PUBLIC_REPO_URL}): Build #${EXTRA_VERSION_IDENTIFIER} of branch [${NEW_BRANCH}](${PUBLIC_REPO_URL}/tree/${NEW_BRANCH}) has been published.\n\nDrive safe! 🚗💨",
|
||||
"color": 4321431
|
||||
}
|
||||
]
|
||||
|
||||
+24
-4
@@ -1,6 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
from types import SimpleNamespace
|
||||
|
||||
import cereal.messaging as messaging
|
||||
|
||||
@@ -14,6 +16,7 @@ from openpilot.common.realtime import config_realtime_process, Priority, Ratekee
|
||||
from openpilot.selfdrive.pandad import can_list_to_can_capnp
|
||||
from openpilot.selfdrive.car.car_helpers import get_car, get_one_can
|
||||
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
|
||||
from openpilot.selfdrive.car.param_manager import ParamManager
|
||||
from openpilot.selfdrive.controls.lib.events import Events
|
||||
|
||||
REPLAY = "REPLAY" in os.environ
|
||||
@@ -90,6 +93,10 @@ class Car:
|
||||
|
||||
self.events = Events()
|
||||
|
||||
self.param_manager: ParamManager = ParamManager()
|
||||
self.param_manager.update(self.params)
|
||||
self._params_list: SimpleNamespace = self.param_manager.get_params()
|
||||
|
||||
# card is driven by can recv, expected at 100Hz
|
||||
self.rk = Ratekeeper(100, print_delay_threshold=None)
|
||||
|
||||
@@ -98,7 +105,7 @@ class Car:
|
||||
|
||||
# Update carState from CAN
|
||||
can_strs = messaging.drain_sock_raw(self.can_sock, wait_for_one=True)
|
||||
CS = self.CI.update(self.CC_prev, can_strs)
|
||||
CS = self.CI.update(self.CC_prev, can_strs, self._params_list)
|
||||
|
||||
self.sm.update(0)
|
||||
|
||||
@@ -186,10 +193,23 @@ class Car:
|
||||
self.initialized_prev = initialized
|
||||
self.CS_prev = CS.as_reader()
|
||||
|
||||
def sp_params_thread(self, event: threading.Event) -> None:
|
||||
while not event.is_set():
|
||||
self.param_manager.update(self.params)
|
||||
self._params_list = self.param_manager.get_params()
|
||||
time.sleep(0.1)
|
||||
|
||||
def card_thread(self):
|
||||
while True:
|
||||
self.step()
|
||||
self.rk.monitor_time()
|
||||
event = threading.Event()
|
||||
thread = threading.Thread(target=self.sp_params_thread, args=(event, ))
|
||||
try:
|
||||
thread.start()
|
||||
while True:
|
||||
self.step()
|
||||
self.rk.monitor_time()
|
||||
finally:
|
||||
event.set()
|
||||
thread.join()
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -30,9 +30,6 @@ class CarController(CarControllerBase):
|
||||
|
||||
self.sm = messaging.SubMaster(['longitudinalPlanSP'])
|
||||
self.param_s = Params()
|
||||
self.is_metric = self.param_s.get_bool("IsMetric")
|
||||
self.speed_limit_control_enabled = False
|
||||
self.last_speed_limit_sign_tap = False
|
||||
self.last_speed_limit_sign_tap_prev = False
|
||||
self.speed_limit = 0.
|
||||
self.speed_limit_offset = 0
|
||||
@@ -72,23 +69,19 @@ class CarController(CarControllerBase):
|
||||
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
|
||||
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
|
||||
|
||||
if self.frame % 200 == 0:
|
||||
self.speed_limit_control_enabled = self.param_s.get_bool("EnableSlc")
|
||||
self.is_metric = self.param_s.get_bool("IsMetric")
|
||||
self.last_speed_limit_sign_tap = self.param_s.get_bool("LastSpeedLimitSignTap")
|
||||
self.v_cruise_min = FCA_V_CRUISE_MIN[self.is_metric] * (CV.KPH_TO_MPH if not self.is_metric else 1)
|
||||
self.v_cruise_min = FCA_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
|
||||
|
||||
can_sends = []
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if not self.last_speed_limit_sign_tap_prev and self.last_speed_limit_sign_tap:
|
||||
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
|
||||
self.sl_force_active_timer = self.frame
|
||||
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
|
||||
self.last_speed_limit_sign_tap_prev = self.last_speed_limit_sign_tap
|
||||
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
|
||||
|
||||
sl_force_active = self.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not self.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (self.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
slc_active = not sl_inactive and not sl_temp_inactive
|
||||
|
||||
self.slc_active_stock = slc_active
|
||||
|
||||
@@ -91,10 +91,12 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
self.sp_update_params()
|
||||
|
||||
self.CS.button_events.extend(create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise}))
|
||||
self.CS.button_events.extend(create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}))
|
||||
self.CS.button_events = [
|
||||
*self.CS.button_events,
|
||||
*create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise}),
|
||||
*create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}),
|
||||
]
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
|
||||
|
||||
@@ -72,10 +72,12 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
self.sp_update_params()
|
||||
|
||||
self.CS.button_events.extend(create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise}))
|
||||
self.CS.button_events.extend(create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}))
|
||||
self.CS.button_events = [
|
||||
*self.CS.button_events,
|
||||
*create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise}),
|
||||
*create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}),
|
||||
]
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
|
||||
|
||||
@@ -204,7 +204,6 @@ class CarInterface(CarInterfaceBase):
|
||||
# returns a car.CarState
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_loopback)
|
||||
self.sp_update_params()
|
||||
|
||||
distance_button = 0
|
||||
|
||||
@@ -218,7 +217,10 @@ class CarInterface(CarInterfaceBase):
|
||||
]
|
||||
distance_button = self.CS.distance_button
|
||||
|
||||
self.CS.button_events.extend(create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}))
|
||||
self.CS.button_events = [
|
||||
*self.CS.button_events,
|
||||
*create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}),
|
||||
]
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
|
||||
|
||||
@@ -132,9 +132,6 @@ class CarController(CarControllerBase):
|
||||
|
||||
self.sm = messaging.SubMaster(['longitudinalPlanSP'])
|
||||
self.param_s = Params()
|
||||
self.is_metric = self.param_s.get_bool("IsMetric")
|
||||
self.speed_limit_control_enabled = False
|
||||
self.last_speed_limit_sign_tap = False
|
||||
self.last_speed_limit_sign_tap_prev = False
|
||||
self.speed_limit = 0.
|
||||
self.speed_limit_offset = 0
|
||||
@@ -173,11 +170,7 @@ class CarController(CarControllerBase):
|
||||
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
|
||||
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
|
||||
|
||||
if self.frame % 200 == 0:
|
||||
self.speed_limit_control_enabled = self.param_s.get_bool("EnableSlc")
|
||||
self.is_metric = self.param_s.get_bool("IsMetric")
|
||||
self.last_speed_limit_sign_tap = self.param_s.get_bool("LastSpeedLimitSignTap")
|
||||
self.v_cruise_min = HONDA_V_CRUISE_MIN[self.is_metric] * (CV.KPH_TO_MPH if not self.is_metric else 1)
|
||||
self.v_cruise_min = HONDA_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
|
||||
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
@@ -213,14 +206,14 @@ class CarController(CarControllerBase):
|
||||
self.params.STEER_LOOKUP_BP, self.params.STEER_LOOKUP_V))
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if not self.last_speed_limit_sign_tap_prev and self.last_speed_limit_sign_tap:
|
||||
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
|
||||
self.sl_force_active_timer = self.frame
|
||||
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
|
||||
self.last_speed_limit_sign_tap_prev = self.last_speed_limit_sign_tap
|
||||
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
|
||||
|
||||
sl_force_active = self.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not self.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (self.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
slc_active = not sl_inactive and not sl_temp_inactive
|
||||
|
||||
self.slc_active_stock = slc_active
|
||||
@@ -432,8 +425,8 @@ class CarController(CarControllerBase):
|
||||
return min(target_speed_kph, curve_speed)
|
||||
|
||||
def get_button_control(self, CS, final_speed, v_cruise_kph_prev):
|
||||
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not self.is_metric else 1))
|
||||
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not self.is_metric else CV.MS_TO_KPH))
|
||||
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1))
|
||||
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not CS.params_list.is_metric else CV.MS_TO_KPH))
|
||||
cruise_button = self.get_button_type(self.button_type)
|
||||
return cruise_button
|
||||
|
||||
|
||||
@@ -174,11 +174,6 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 239], [0, 239]]
|
||||
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.,20], [0.,20]]
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.4,0.3], [0,0]]
|
||||
tire_stiffness_factor = 0.8467
|
||||
ret.longitudinalTuning.kpBP = [0., 5., 35.]
|
||||
ret.longitudinalTuning.kpV = [2.4, 1.6, 0.8]
|
||||
ret.longitudinalTuning.kiBP = [0., 35.]
|
||||
ret.longitudinalTuning.kiV = [0.2, 0.16]
|
||||
|
||||
elif candidate in (CAR.HONDA_ODYSSEY, CAR.HONDA_ODYSSEY_CHN):
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.28], [0.08]]
|
||||
@@ -266,7 +261,6 @@ class CarInterface(CarInterfaceBase):
|
||||
# returns a car.CarState
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_body)
|
||||
self.sp_update_params()
|
||||
|
||||
self.CS.button_events = [
|
||||
*create_button_events(self.CS.cruise_buttons, self.CS.prev_cruise_buttons, BUTTONS_DICT),
|
||||
@@ -288,21 +282,26 @@ class CarInterface(CarInterfaceBase):
|
||||
else:
|
||||
self.CS.madsEnabled = False
|
||||
|
||||
if not self.CP.pcmCruise or (self.CP.pcmCruise and self.CP.minEnableSpeed > 0) or not self.CP.pcmCruiseSpeed:
|
||||
min_enable_speed_pcm = self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed
|
||||
|
||||
if not self.CP.pcmCruise or min_enable_speed_pcm or not self.CP.pcmCruiseSpeed:
|
||||
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads else False if self.CP.pcmCruise else self.CS.accEnabled
|
||||
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads or min_enable_speed_pcm \
|
||||
else False if self.CP.pcmCruise \
|
||||
else self.CS.accEnabled
|
||||
|
||||
if self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed:
|
||||
if min_enable_speed_pcm:
|
||||
if ret.gasPressed and not ret.cruiseState.enabled:
|
||||
self.CS.accEnabled = False
|
||||
self.CS.accEnabled = ret.cruiseState.enabled or self.CS.accEnabled
|
||||
if ret.cruiseState.enabled and not self.CS.out.cruiseState.enabled:
|
||||
self.CS.accEnabled = True
|
||||
elif not ret.cruiseState.enabled:
|
||||
self.CS.accEnabled = False
|
||||
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS,
|
||||
min_enable_speed_pcm=(self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed),
|
||||
gap_button=(self.CS.cruise_setting == 3))
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=(self.CS.cruise_setting == 3))
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
|
||||
@@ -72,9 +72,6 @@ class CarController(CarControllerBase):
|
||||
self.sm = messaging.SubMaster(sub_services)
|
||||
|
||||
self.param_s = Params()
|
||||
self.is_metric = self.param_s.get_bool("IsMetric")
|
||||
self.speed_limit_control_enabled = False
|
||||
self.last_speed_limit_sign_tap = False
|
||||
self.last_speed_limit_sign_tap_prev = False
|
||||
self.speed_limit = 0.
|
||||
self.speed_limit_offset = 0
|
||||
@@ -127,11 +124,7 @@ class CarController(CarControllerBase):
|
||||
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
|
||||
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
|
||||
|
||||
if self.frame % 200 == 0:
|
||||
self.speed_limit_control_enabled = self.param_s.get_bool("EnableSlc")
|
||||
self.is_metric = self.param_s.get_bool("IsMetric")
|
||||
self.last_speed_limit_sign_tap = self.param_s.get_bool("LastSpeedLimitSignTap")
|
||||
self.v_cruise_min = HYUNDAI_V_CRUISE_MIN[self.is_metric] * (CV.KPH_TO_MPH if not self.is_metric else 1)
|
||||
self.v_cruise_min = HYUNDAI_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
|
||||
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
@@ -175,14 +168,14 @@ class CarController(CarControllerBase):
|
||||
blinking_icon = (self.frame - self.disengage_blink) * DT_CTRL < 1.0 if self.lat_disengage_init else False
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if not self.last_speed_limit_sign_tap_prev and self.last_speed_limit_sign_tap:
|
||||
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
|
||||
self.sl_force_active_timer = self.frame
|
||||
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
|
||||
self.last_speed_limit_sign_tap_prev = self.last_speed_limit_sign_tap
|
||||
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
|
||||
|
||||
sl_force_active = self.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not self.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (self.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
slc_active = not sl_inactive and not sl_temp_inactive
|
||||
|
||||
self.slc_active_stock = slc_active
|
||||
@@ -235,7 +228,7 @@ class CarController(CarControllerBase):
|
||||
if hda2:
|
||||
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
|
||||
if self.frame % 2 == 0:
|
||||
can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CC.enabled and CS.out.cruiseState.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
|
||||
can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CS, CC.enabled and CS.out.cruiseState.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
|
||||
set_speed_in_units, hud_control))
|
||||
self.accel_last = accel
|
||||
else:
|
||||
@@ -433,8 +426,8 @@ class CarController(CarControllerBase):
|
||||
return min(target_speed_kph, curve_speed)
|
||||
|
||||
def get_button_control(self, CS, final_speed, v_cruise_kph_prev):
|
||||
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not self.is_metric else 1))
|
||||
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not self.is_metric else CV.MS_TO_KPH))
|
||||
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1))
|
||||
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not CS.params_list.is_metric else CV.MS_TO_KPH))
|
||||
cruise_button = self.get_button_type(self.button_type)
|
||||
return cruise_button
|
||||
|
||||
|
||||
@@ -62,6 +62,11 @@ class CarState(CarStateBase):
|
||||
self.escc_aeb_dec_cmd = 0
|
||||
self._speed_limit_clu = 0
|
||||
|
||||
def get_main_enabled(self, ret) -> bool:
|
||||
if self.prev_main_buttons != 1 and self.main_buttons[-1] == 1:
|
||||
self.mainEnabled = not self.mainEnabled
|
||||
return ret.cruiseState.available and self.mainEnabled
|
||||
|
||||
def update(self, cp, cp_cam):
|
||||
if self.CP.carFingerprint in CANFD_CAR:
|
||||
return self.update_canfd(cp, cp_cam)
|
||||
@@ -112,7 +117,7 @@ class CarState(CarStateBase):
|
||||
# cruise state
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
# These are not used for engage/disengage since openpilot keeps track of state using the buttons
|
||||
ret.cruiseState.available = cp.vl["TCS13"]["ACCEnable"] == 0 and self.mainEnabled
|
||||
ret.cruiseState.available = cp.vl["TCS13"]["ACCEnable"] == 0
|
||||
ret.cruiseState.enabled = cp.vl["TCS13"]["ACC_REQ"] == 1
|
||||
ret.cruiseState.standstill = False
|
||||
ret.cruiseState.nonAdaptive = False
|
||||
@@ -207,17 +212,12 @@ class CarState(CarStateBase):
|
||||
self.cruise_buttons.extend(cp.vl_all["CLU11"]["CF_Clu_CruiseSwState"])
|
||||
self.main_buttons.extend(cp.vl_all["CLU11"]["CF_Clu_CruiseSwMain"])
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
if self.prev_main_buttons != 1:
|
||||
if self.main_buttons[-1] == 1:
|
||||
self.mainEnabled = not self.mainEnabled
|
||||
ret.cruiseState.available = ret.cruiseState.available and self.mainEnabled
|
||||
ret.cruiseState.available = self.get_main_enabled(ret)
|
||||
self.prev_mads_enabled = self.mads_enabled
|
||||
self.prev_lfa_enabled = self.lfa_enabled
|
||||
if self.CP.spFlags & HyundaiFlagsSP.SP_CAN_LFA_BTN:
|
||||
self.lfa_enabled = cp.vl["BCM_PO_11"]["LFA_Pressed"]
|
||||
|
||||
self.mads_enabled = False if not self.control_initialized else ret.cruiseState.available
|
||||
|
||||
if self.CP.spFlags & HyundaiFlagsSP.SP_NAV_MSG or self.CP.spFlags & HyundaiFlagsSP.SP_LKAS12:
|
||||
self._update_traffic_signals(cp, cp_cam)
|
||||
ret.cruiseState.speedLimit = self._calculate_speed_limit() * speed_conv
|
||||
@@ -282,6 +282,7 @@ class CarState(CarStateBase):
|
||||
ret.cruiseState.standstill = False
|
||||
else:
|
||||
cp_cruise_info = cp_cam if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else cp
|
||||
ret.cruiseState.available = cp_cruise_info.vl["SCC_CONTROL"]["MainMode_ACC"] == 1
|
||||
ret.cruiseState.enabled = cp_cruise_info.vl["SCC_CONTROL"]["ACCMode"] in (1, 2)
|
||||
ret.cruiseState.standstill = cp_cruise_info.vl["SCC_CONTROL"]["CRUISE_STANDSTILL"] == 1
|
||||
ret.cruiseState.speed = cp_cruise_info.vl["SCC_CONTROL"]["VSetDis"] * speed_factor
|
||||
@@ -298,6 +299,8 @@ class CarState(CarStateBase):
|
||||
self.prev_main_buttons = self.main_buttons[-1]
|
||||
self.cruise_buttons.extend(cp.vl_all[self.cruise_btns_msg_canfd]["CRUISE_BUTTONS"])
|
||||
self.main_buttons.extend(cp.vl_all[self.cruise_btns_msg_canfd]["ADAPTIVE_CRUISE_MAIN_BTN"])
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
ret.cruiseState.available = self.get_main_enabled(ret)
|
||||
self.prev_mads_enabled = self.mads_enabled
|
||||
self.prev_lfa_enabled = self.lfa_enabled
|
||||
self.lfa_enabled = cp.vl[self.cruise_btns_msg_canfd]["LFA_BTN"]
|
||||
|
||||
@@ -121,7 +121,7 @@ def create_lfahda_cluster(packer, CAN, enabled, lat_active, lateral_paused, blin
|
||||
return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values)
|
||||
|
||||
|
||||
def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control):
|
||||
def create_acc_control(packer, CAN, CS, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control):
|
||||
jerk = 5
|
||||
jn = jerk / 50
|
||||
if not enabled or gas_override:
|
||||
@@ -132,7 +132,7 @@ def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_ov
|
||||
|
||||
values = {
|
||||
"ACCMode": 0 if not enabled else (2 if gas_override else 1),
|
||||
"MainMode_ACC": 1,
|
||||
"MainMode_ACC": 1 if CS.mainEnabled else 0,
|
||||
"StopReq": 1 if stopping else 0,
|
||||
"aReqValue": a_val,
|
||||
"aReqRaw": a_raw,
|
||||
|
||||
@@ -203,28 +203,32 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
self.sp_update_params()
|
||||
|
||||
self.CS.button_events.extend(create_button_events(self.CS.cruise_buttons[-1], self.CS.prev_cruise_buttons, BUTTONS_DICT))
|
||||
self.CS.button_events.extend(create_button_events(self.CS.lfa_enabled, self.CS.prev_lfa_enabled, {1: ButtonType.altButton1}))
|
||||
self.CS.button_events.extend(create_button_events(self.CS.main_buttons[-1], self.CS.prev_main_buttons, {1: ButtonType.altButton3}))
|
||||
self.CS.button_events = [
|
||||
*create_button_events(self.CS.cruise_buttons[-1], self.CS.prev_cruise_buttons, BUTTONS_DICT),
|
||||
*create_button_events(self.CS.lfa_enabled, self.CS.prev_lfa_enabled, {1: ButtonType.altButton1}),
|
||||
*create_button_events(self.CS.main_buttons[-1], self.CS.prev_main_buttons, {1: ButtonType.altButton3}),
|
||||
]
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
self.CS.button_events, c.vCruise)
|
||||
|
||||
self.CS.mads_enabled = False if not self.mads_main_toggle else self.CS.mads_enabled
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if any(b.type in (ButtonType.altButton3, ButtonType.cancel) and not b.pressed for b in self.CS.button_events):
|
||||
self.CS.accEnabled = True
|
||||
if self.enable_mads:
|
||||
if not self.CS.prev_mads_enabled and self.CS.mads_enabled:
|
||||
self.CS.madsEnabled = True
|
||||
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
|
||||
self.CS.madsEnabled = not self.CS.madsEnabled
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
else:
|
||||
|
||||
if self.enable_mads:
|
||||
if not self.CS.prev_mads_enabled and self.CS.mads_enabled and \
|
||||
any(b.type == ButtonType.altButton3 for b in self.CS.button_events):
|
||||
self.CS.madsEnabled = True
|
||||
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
|
||||
self.CS.madsEnabled = not self.CS.madsEnabled
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
|
||||
if not ret.cruiseState.available and self.CS.out.cruiseState.available:
|
||||
self.CS.madsEnabled = False
|
||||
|
||||
if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed:
|
||||
|
||||
+15
-33
@@ -7,6 +7,7 @@ import tomllib
|
||||
from abc import abstractmethod, ABC
|
||||
from difflib import SequenceMatcher
|
||||
from enum import StrEnum
|
||||
from types import SimpleNamespace
|
||||
from typing import Any, NamedTuple
|
||||
from collections.abc import Callable
|
||||
from functools import cache
|
||||
@@ -19,6 +20,7 @@ from openpilot.common.numpy_fast import clip
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.common.realtime import DT_CTRL
|
||||
from openpilot.selfdrive.car import apply_hysteresis, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness, STD_CARGO_KG, ButtonEvents
|
||||
from openpilot.selfdrive.car.param_manager import ParamManager
|
||||
from openpilot.selfdrive.car.values import PLATFORMS
|
||||
from openpilot.selfdrive.controls.lib.desire_helper import get_min_lateral_speed
|
||||
from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, V_CRUISE_UNSET, get_friction
|
||||
@@ -238,19 +240,10 @@ class CarInterfaceBase(ABC):
|
||||
self.mads_ndlob = self.enable_mads and not self.mads_disengage_lateral_on_brake
|
||||
self.gear_warning = 0
|
||||
self.cruise_cancelled_btn = True
|
||||
self.acc_mads_combo = self.param_s.get_bool("AccMadsCombo")
|
||||
self.is_metric = self.param_s.get_bool("IsMetric")
|
||||
self.below_speed_pause = self.param_s.get_bool("BelowSpeedPause")
|
||||
self.pause_lateral_speed = int(self.param_s.get("PauseLateralSpeed", encoding="utf8"))
|
||||
self.prev_acc_mads_combo = False
|
||||
self.mads_event_lock = True
|
||||
self.gap_button_counter = 0
|
||||
self.experimental_mode_hold = False
|
||||
self.experimental_mode = self.param_s.get_bool("ExperimentalMode")
|
||||
self._frame = 0
|
||||
self.reverse_dm_cam = self.param_s.get_bool("ReverseDmCam")
|
||||
self.mads_main_toggle = self.param_s.get_bool("MadsCruiseMain")
|
||||
self.lkas_toggle = self.param_s.get_bool("LkasToggle")
|
||||
self.last_mads_init = 0.
|
||||
self.madsEnabledInit = False
|
||||
self.madsEnabledInitPrev = False
|
||||
@@ -421,13 +414,14 @@ class CarInterfaceBase(ABC):
|
||||
def _update(self, c: car.CarControl) -> car.CarState:
|
||||
pass
|
||||
|
||||
def update(self, c: car.CarControl, can_strings: list[bytes]) -> car.CarState:
|
||||
def update(self, c: car.CarControl, can_strings: list[bytes], params_list: SimpleNamespace) -> car.CarState:
|
||||
# parse can
|
||||
for cp in self.can_parsers:
|
||||
if cp is not None:
|
||||
cp.update_strings(can_strings)
|
||||
|
||||
self.CS.button_events = []
|
||||
self.CS.params_list = params_list
|
||||
|
||||
# get CarState
|
||||
ret = self._update(c)
|
||||
@@ -472,11 +466,11 @@ class CarInterfaceBase(ABC):
|
||||
else:
|
||||
events.add(EventName.wrongGear)
|
||||
if cs_out.gearShifter == GearShifter.reverse:
|
||||
if not self.reverse_dm_cam and cs_out.vEgo < 5:
|
||||
if not self.CS.params_list.reverse_dm_cam and cs_out.vEgo < 5:
|
||||
events.add(EventName.spReverseGear)
|
||||
elif cs_out.vEgo >= 5:
|
||||
events.add(EventName.reverseGear)
|
||||
if not cs_out.cruiseState.available:
|
||||
if not cs_out.cruiseState.available and cs_out.cruiseState.enabled:
|
||||
events.add(EventName.wrongCarMode)
|
||||
if cs_out.espDisabled:
|
||||
events.add(EventName.espDisabled)
|
||||
@@ -554,7 +548,7 @@ class CarInterfaceBase(ABC):
|
||||
return v_cruise != V_CRUISE_UNSET
|
||||
|
||||
def get_acc_mads(self, cruiseState_enabled, acc_enabled, mads_enabled):
|
||||
if self.acc_mads_combo:
|
||||
if self.CS.params_list.acc_mads_combo:
|
||||
if not self.prev_acc_mads_combo and (cruiseState_enabled or acc_enabled):
|
||||
mads_enabled = True
|
||||
self.prev_acc_mads_combo = (cruiseState_enabled or acc_enabled)
|
||||
@@ -594,7 +588,7 @@ class CarInterfaceBase(ABC):
|
||||
def get_sp_cruise_main_state(self, cs_out, CS):
|
||||
if not CS.control_initialized:
|
||||
mads_enabled = False
|
||||
elif not self.mads_main_toggle:
|
||||
elif not self.CS.params_list.mads_main_toggle:
|
||||
mads_enabled = False
|
||||
else:
|
||||
mads_enabled = cs_out.cruiseState.available
|
||||
@@ -606,7 +600,7 @@ class CarInterfaceBase(ABC):
|
||||
self.madsEnabledInit = False
|
||||
self.madsEnabledInitPrev = False
|
||||
return False
|
||||
if not self.mads_main_toggle or self.prev_acc_mads_combo:
|
||||
if not self.CS.params_list.mads_main_toggle or self.prev_acc_mads_combo:
|
||||
return CS.madsEnabled
|
||||
if not self.madsEnabledInit and CS.madsEnabled:
|
||||
self.madsEnabledInit = True
|
||||
@@ -621,9 +615,8 @@ class CarInterfaceBase(ABC):
|
||||
else:
|
||||
return CS.madsEnabled
|
||||
|
||||
def get_sp_common_state(self, cs_out, CS, min_enable_speed_pcm=False, gear_allowed=True, gap_button=False):
|
||||
cs_out.cruiseState.enabled = CS.accEnabled if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed or min_enable_speed_pcm else \
|
||||
cs_out.cruiseState.enabled
|
||||
def get_sp_common_state(self, cs_out, CS, gear_allowed=True, gap_button=False):
|
||||
cs_out.cruiseState.enabled = CS.accEnabled if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed else cs_out.cruiseState.enabled
|
||||
|
||||
if not self.enable_mads:
|
||||
if cs_out.cruiseState.enabled and not CS.out.cruiseState.enabled:
|
||||
@@ -634,9 +627,9 @@ class CarInterfaceBase(ABC):
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
self.toggle_exp_mode(gap_button)
|
||||
|
||||
lane_change_speed_min = get_min_lateral_speed(self.pause_lateral_speed, self.is_metric)
|
||||
lane_change_speed_min = get_min_lateral_speed(self.CS.params_list.pause_lateral_speed, self.CS.params_list.is_metric)
|
||||
|
||||
cs_out.belowLaneChangeSpeed = cs_out.vEgo < lane_change_speed_min and self.below_speed_pause
|
||||
cs_out.belowLaneChangeSpeed = cs_out.vEgo < lane_change_speed_min and self.CS.params_list.below_speed_pause
|
||||
|
||||
if cs_out.gearShifter in [GearShifter.park, GearShifter.reverse] or cs_out.doorOpen or \
|
||||
(cs_out.seatbeltUnlatched and cs_out.gearShifter != GearShifter.park):
|
||||
@@ -669,7 +662,7 @@ class CarInterfaceBase(ABC):
|
||||
if self.gap_button_counter > 50:
|
||||
self.gap_button_counter = 0
|
||||
self.experimental_mode_hold = True
|
||||
self.param_s.put_bool_nonblocking("ExperimentalMode", not self.experimental_mode)
|
||||
self.param_s.put_bool_nonblocking("ExperimentalMode", not self.CS.params_list.experimental_mode)
|
||||
else:
|
||||
self.gap_button_counter = 0
|
||||
self.experimental_mode_hold = False
|
||||
@@ -735,17 +728,6 @@ class CarInterfaceBase(ABC):
|
||||
|
||||
return events, cs_out
|
||||
|
||||
def sp_update_params(self):
|
||||
self.experimental_mode = self.param_s.get_bool("ExperimentalMode")
|
||||
self._frame += 1
|
||||
if self._frame % 100 == 0:
|
||||
self.is_metric = self.param_s.get_bool("IsMetric")
|
||||
self.below_speed_pause = self.param_s.get_bool("BelowSpeedPause")
|
||||
self.pause_lateral_speed = int(self.param_s.get("PauseLateralSpeed", encoding="utf8"))
|
||||
if self._frame % 300 == 0:
|
||||
self._frame = 0
|
||||
self.reverse_dm_cam = self.param_s.get_bool("ReverseDmCam")
|
||||
|
||||
class RadarInterfaceBase(ABC):
|
||||
def __init__(self, CP):
|
||||
self.rcp = None
|
||||
@@ -776,7 +758,6 @@ class CarStateBase(ABC):
|
||||
self.cluster_speed_hyst_gap = 0.0
|
||||
self.cluster_min_speed = 0.0 # min speed before dropping to 0
|
||||
|
||||
self.param_s = Params()
|
||||
self.accEnabled = False
|
||||
self.madsEnabled = False
|
||||
self.disengageByBrake = False
|
||||
@@ -785,6 +766,7 @@ class CarStateBase(ABC):
|
||||
self.control_initialized = False
|
||||
|
||||
self.button_events: list[capnp.lib.capnp._DynamicStructBuilder] = []
|
||||
self.params_list: SimpleNamespace = ParamManager().get_params()
|
||||
|
||||
Q = [[0.0, 0.0], [0.0, 100.0]]
|
||||
R = 0.3
|
||||
|
||||
@@ -24,9 +24,6 @@ class CarController(CarControllerBase):
|
||||
|
||||
self.sm = messaging.SubMaster(['longitudinalPlanSP'])
|
||||
self.param_s = Params()
|
||||
self.is_metric = self.param_s.get_bool("IsMetric")
|
||||
self.speed_limit_control_enabled = False
|
||||
self.last_speed_limit_sign_tap = False
|
||||
self.last_speed_limit_sign_tap_prev = False
|
||||
self.speed_limit = 0.
|
||||
self.speed_limit_offset = 0
|
||||
@@ -65,23 +62,19 @@ class CarController(CarControllerBase):
|
||||
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
|
||||
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
|
||||
|
||||
if self.frame % 200 == 0:
|
||||
self.speed_limit_control_enabled = self.param_s.get_bool("EnableSlc")
|
||||
self.is_metric = self.param_s.get_bool("IsMetric")
|
||||
self.last_speed_limit_sign_tap = self.param_s.get_bool("LastSpeedLimitSignTap")
|
||||
self.v_cruise_min = MAZDA_V_CRUISE_MIN[self.is_metric] * (CV.KPH_TO_MPH if not self.is_metric else 1)
|
||||
self.v_cruise_min = MAZDA_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
|
||||
|
||||
can_sends = []
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if not self.last_speed_limit_sign_tap_prev and self.last_speed_limit_sign_tap:
|
||||
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
|
||||
self.sl_force_active_timer = self.frame
|
||||
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
|
||||
self.last_speed_limit_sign_tap_prev = self.last_speed_limit_sign_tap
|
||||
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
|
||||
|
||||
sl_force_active = self.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not self.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (self.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
slc_active = not sl_inactive and not sl_temp_inactive
|
||||
|
||||
self.slc_active_stock = slc_active
|
||||
@@ -229,8 +222,8 @@ class CarController(CarControllerBase):
|
||||
return min(target_speed_kph, curve_speed)
|
||||
|
||||
def get_button_control(self, CS, final_speed, v_cruise_kph_prev):
|
||||
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not self.is_metric else 1))
|
||||
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not self.is_metric else CV.MS_TO_KPH))
|
||||
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1))
|
||||
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not CS.params_list.is_metric else CV.MS_TO_KPH))
|
||||
cruise_button = self.get_button_type(self.button_type)
|
||||
return cruise_button
|
||||
|
||||
|
||||
@@ -37,11 +37,13 @@ class CarInterface(CarInterfaceBase):
|
||||
# returns a car.CarState
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
self.sp_update_params()
|
||||
|
||||
# TODO: add button types for inc and dec
|
||||
self.CS.button_events.extend(create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise}))
|
||||
self.CS.button_events.extend(create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}))
|
||||
self.CS.button_events = [
|
||||
*self.CS.button_events,
|
||||
*create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise}),
|
||||
*create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}),
|
||||
]
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ class CarInterface(CarInterfaceBase):
|
||||
# returns a car.CarState
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_adas, self.cp_cam)
|
||||
self.sp_update_params()
|
||||
|
||||
self.CS.button_events = create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise})
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
from openpilot.common.params import Params
|
||||
|
||||
|
||||
class ParamManager:
|
||||
def __init__(self):
|
||||
self._params_list: SimpleNamespace = self._create_namespace({
|
||||
"acc_mads_combo": False,
|
||||
"below_speed_pause": False,
|
||||
"experimental_mode": False,
|
||||
"is_metric": False,
|
||||
"last_speed_limit_sign_tap": False,
|
||||
"mads_main_toggle": False,
|
||||
"pause_lateral_speed": 0,
|
||||
"reverse_acc_change": False,
|
||||
"reverse_dm_cam": False,
|
||||
"speed_limit_control_enabled": False,
|
||||
"subaru_manual_parking_brake": False,
|
||||
"toyota_auto_lock_by_speed": False,
|
||||
"toyota_auto_unlock_by_shifter": False,
|
||||
"toyota_lkas_toggle": False,
|
||||
"toyota_sng_hack": False,
|
||||
})
|
||||
|
||||
@staticmethod
|
||||
def _create_namespace(data: dict) -> SimpleNamespace:
|
||||
return SimpleNamespace(**data)
|
||||
|
||||
def get_params(self) -> SimpleNamespace:
|
||||
return self._params_list
|
||||
|
||||
def update(self, params: Params) -> None:
|
||||
self._params_list = self._create_namespace({
|
||||
"acc_mads_combo": params.get_bool("AccMadsCombo"),
|
||||
"below_speed_pause": params.get_bool("BelowSpeedPause"),
|
||||
"experimental_mode": params.get_bool("ExperimentalMode"),
|
||||
"is_metric": params.get_bool("IsMetric"),
|
||||
"last_speed_limit_sign_tap": params.get_bool("LastSpeedLimitSignTap"),
|
||||
"mads_main_toggle": params.get_bool("MadsCruiseMain"),
|
||||
"pause_lateral_speed": int(params.get("PauseLateralSpeed", encoding="utf8")),
|
||||
"reverse_acc_change": params.get_bool("ReverseAccChange"),
|
||||
"reverse_dm_cam": params.get_bool("ReverseDmCam"),
|
||||
"speed_limit_control_enabled": params.get_bool("EnableSlc"),
|
||||
"subaru_manual_parking_brake": params.get_bool("SubaruManualParkingBrakeSng"),
|
||||
"toyota_auto_lock_by_speed": params.get_bool("ToyotaAutoLockBySpeed"),
|
||||
"toyota_auto_unlock_by_shifter": params.get_bool("ToyotaAutoUnlockByShifter"),
|
||||
"toyota_lkas_toggle": params.get_bool("LkasToggle"),
|
||||
"toyota_sng_hack": params.get_bool("ToyotaSnG"),
|
||||
})
|
||||
@@ -1,6 +1,5 @@
|
||||
from cereal import car
|
||||
from openpilot.common.numpy_fast import clip, interp
|
||||
from openpilot.common.params import Params
|
||||
from opendbc.can.packer import CANPacker
|
||||
from openpilot.selfdrive.car import apply_driver_steer_torque_limits, common_fault_avoidance
|
||||
from openpilot.selfdrive.car.interfaces import CarControllerBase
|
||||
@@ -25,12 +24,9 @@ class CarController(CarControllerBase):
|
||||
self.cruise_button_prev = 0
|
||||
self.steer_rate_counter = 0
|
||||
|
||||
self.param_s = Params()
|
||||
|
||||
self.subaru_sng = False
|
||||
if CP.spFlags & SubaruFlagsSP.SP_SUBARU_SNG:
|
||||
self.subaru_sng = True
|
||||
self.manual_parking_brake = self.param_s.get_bool("SubaruManualParkingBrakeSng")
|
||||
self.prev_close_distance = 0
|
||||
self.prev_standstill = False
|
||||
self.standstill_start = 0
|
||||
@@ -47,9 +43,6 @@ class CarController(CarControllerBase):
|
||||
hud_control = CC.hudControl
|
||||
pcm_cancel_cmd = CC.cruiseControl.cancel
|
||||
|
||||
if self.frame % 250 == 0 and self.subaru_sng:
|
||||
self.manual_parking_brake = self.param_s.get_bool("SubaruManualParkingBrakeSng")
|
||||
|
||||
can_sends = []
|
||||
|
||||
# *** steering ***
|
||||
@@ -191,7 +184,7 @@ class CarController(CarControllerBase):
|
||||
and CS.close_distance > self.prev_close_distance): # distance with lead car is increasing
|
||||
self.sng_acc_resume = True
|
||||
elif not (self.CP.flags & (SubaruFlags.GLOBAL_GEN2 | SubaruFlags.HYBRID)):
|
||||
if self.manual_parking_brake:
|
||||
if CS.params_list.subaru_manual_parking_brake and self.subaru_sng:
|
||||
# Send brake message with non-zero speed in standstill to avoid non-EPB ACC disengage
|
||||
if (CC.enabled # ACC active
|
||||
and CS.car_follow == 1 # lead car
|
||||
|
||||
@@ -116,7 +116,6 @@ class CarInterface(CarInterfaceBase):
|
||||
def _update(self, c):
|
||||
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_body)
|
||||
self.sp_update_params()
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from cereal import car
|
||||
from common.conversions import Conversions as CV
|
||||
from openpilot.common.numpy_fast import clip, interp
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.selfdrive.car import apply_meas_steer_torque_limits, apply_std_steer_angle_limits, common_fault_avoidance, \
|
||||
create_gas_interceptor_command, make_can_msg
|
||||
from openpilot.selfdrive.car.interfaces import CarControllerBase
|
||||
@@ -52,27 +51,16 @@ class CarController(CarControllerBase):
|
||||
self.gas = 0
|
||||
self.accel = 0
|
||||
|
||||
self.param_s = Params()
|
||||
self._is_metric = self.param_s.get_bool("IsMetric")
|
||||
self._reverse_acc_change = self.param_s.get_bool("ReverseAccChange")
|
||||
self._sng_hack = self.param_s.get_bool("ToyotaSnG")
|
||||
|
||||
self.left_blindspot_debug_enabled = False
|
||||
self.right_blindspot_debug_enabled = False
|
||||
self.last_blindspot_frame = 0
|
||||
|
||||
self._auto_lock_by_speed = self.param_s.get_bool("ToyotaAutoLockBySpeed")
|
||||
self._auto_unlock_by_shifter = self.param_s.get_bool("ToyotaAutoUnlockByShifter")
|
||||
self._auto_lock_speed = 10 * (CV.KPH_TO_MS if self._is_metric else CV.MPH_TO_MS)
|
||||
self._auto_lock_speed = 0.0
|
||||
self._auto_lock_once = False
|
||||
self._gear_prev = GearShifter.park
|
||||
|
||||
def update(self, CC, CS, now_nanos):
|
||||
if self.frame % 200 == 0:
|
||||
self._is_metric = self.param_s.get_bool("IsMetric")
|
||||
self._auto_lock_by_speed = self.param_s.get_bool("ToyotaAutoLockBySpeed")
|
||||
self._auto_unlock_by_shifter = self.param_s.get_bool("ToyotaAutoUnlockByShifter")
|
||||
self._auto_lock_speed = 10 * (CV.KPH_TO_MS if self._is_metric else CV.MPH_TO_MS)
|
||||
self._auto_lock_speed = 10 * (CV.KPH_TO_MS if CS.params_list.is_metric else CV.MPH_TO_MS)
|
||||
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
@@ -88,11 +76,11 @@ class CarController(CarControllerBase):
|
||||
gear = CS.out.gearShifter
|
||||
if not CS.out.doorOpen:
|
||||
if gear == GearShifter.park and self._gear_prev != gear:
|
||||
if self._auto_unlock_by_shifter:
|
||||
if CS.params_list.toyota_auto_unlock_by_shifter:
|
||||
can_sends.append(make_can_msg(0x750, UNLOCK_CMD, 0))
|
||||
self._auto_lock_once = False
|
||||
elif gear == GearShifter.drive and not self._auto_lock_once and CS.out.vEgo >= self._auto_lock_speed:
|
||||
if self._auto_lock_by_speed:
|
||||
if CS.params_list.toyota_auto_lock_by_speed:
|
||||
can_sends.append(make_can_msg(0x750, LOCK_CMD, 0))
|
||||
self._auto_lock_once = True
|
||||
self._gear_prev = gear
|
||||
@@ -173,7 +161,7 @@ class CarController(CarControllerBase):
|
||||
|
||||
# on entering standstill, send standstill request
|
||||
if CS.out.standstill and not self.last_standstill and (self.CP.carFingerprint not in NO_STOP_TIMER_CAR or self.CP.enableGasInterceptorDEPRECATED) and \
|
||||
not self._sng_hack:
|
||||
not CS.params_list.toyota_sng_hack:
|
||||
self.standstill_req = True
|
||||
if CS.pcm_acc_status != 8:
|
||||
# pcm entered standstill or it's disabled
|
||||
@@ -188,7 +176,7 @@ class CarController(CarControllerBase):
|
||||
# we can spam can to cancel the system even if we are using lat only control
|
||||
if (self.frame % 3 == 0 and self.CP.openpilotLongitudinalControl) or pcm_cancel_cmd:
|
||||
lead = hud_control.leadVisible or CS.out.vEgo < 12. # at low speed we always assume the lead is present so ACC can be engaged
|
||||
reverse_acc = 2 if self._reverse_acc_change else 1
|
||||
reverse_acc = 2 if CS.params_list.reverse_acc_change else 1
|
||||
|
||||
# Press distance button until we are at the correct bar length. Only change while enabled to avoid skipping startup popup
|
||||
if self.frame % 6 == 0 and self.CP.openpilotLongitudinalControl:
|
||||
|
||||
@@ -207,7 +207,6 @@ class CarInterface(CarInterfaceBase):
|
||||
# returns a car.CarState
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
self.sp_update_params()
|
||||
|
||||
distance_button = 0
|
||||
|
||||
@@ -221,7 +220,7 @@ class CarInterface(CarInterfaceBase):
|
||||
if self.enable_mads:
|
||||
if not self.CS.prev_mads_enabled and self.CS.mads_enabled:
|
||||
self.CS.madsEnabled = True
|
||||
if self.lkas_toggle:
|
||||
if self.CS.params_list.toyota_lkas_toggle:
|
||||
if self.CS.lta_status_active:
|
||||
if (self.CS.prev_lkas_enabled == 16 and self.CS.lkas_enabled == 0) or \
|
||||
(self.CS.prev_lkas_enabled == 0 and self.CS.lkas_enabled == 16):
|
||||
|
||||
@@ -34,9 +34,6 @@ class CarController(CarControllerBase):
|
||||
|
||||
self.sm = messaging.SubMaster(['longitudinalPlanSP'])
|
||||
self.param_s = Params()
|
||||
self.is_metric = self.param_s.get_bool("IsMetric")
|
||||
self.speed_limit_control_enabled = False
|
||||
self.last_speed_limit_sign_tap = False
|
||||
self.last_speed_limit_sign_tap_prev = False
|
||||
self.speed_limit = 0.
|
||||
self.speed_limit_offset = 0
|
||||
@@ -79,24 +76,20 @@ class CarController(CarControllerBase):
|
||||
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
|
||||
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
|
||||
|
||||
if self.frame % 200 == 0:
|
||||
self.speed_limit_control_enabled = self.param_s.get_bool("EnableSlc")
|
||||
self.is_metric = self.param_s.get_bool("IsMetric")
|
||||
self.last_speed_limit_sign_tap = self.param_s.get_bool("LastSpeedLimitSignTap")
|
||||
self.v_cruise_min = VOLKSWAGEN_V_CRUISE_MIN[self.is_metric] * (CV.KPH_TO_MPH if not self.is_metric else 1)
|
||||
self.v_cruise_min = VOLKSWAGEN_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
can_sends = []
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if not self.last_speed_limit_sign_tap_prev and self.last_speed_limit_sign_tap:
|
||||
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
|
||||
self.sl_force_active_timer = self.frame
|
||||
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
|
||||
self.last_speed_limit_sign_tap_prev = self.last_speed_limit_sign_tap
|
||||
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
|
||||
|
||||
sl_force_active = self.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not self.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (self.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
slc_active = not sl_inactive and not sl_temp_inactive
|
||||
|
||||
self.slc_active_stock = slc_active
|
||||
|
||||
@@ -113,7 +113,6 @@ class CarInterface(CarInterfaceBase):
|
||||
# returns a car.CarState
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_ext, self.CP.transmissionType)
|
||||
self.sp_update_params()
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
|
||||
|
||||
@@ -739,7 +739,9 @@ class Controls:
|
||||
CC.angularVelocity = angular_rate_value
|
||||
|
||||
CC.cruiseControl.override = self.enabled_long and not CC.longActive and self.CP.openpilotLongitudinalControl
|
||||
CC.cruiseControl.cancel = CS.cruiseState.enabled and (not self.enabled_long or (CS.brakePressed and (not self.CS_prev.brakePressed or not CS.standstill)))
|
||||
CC.cruiseControl.cancel = CS.cruiseState.enabled and \
|
||||
(not self.enabled_long or (CS.brakePressed and (not self.CS_prev.brakePressed or not CS.standstill)) or
|
||||
(any(b.type == ButtonType.cancel for b in CS.buttonEvents) and self.CP.carName == "honda"))
|
||||
if self.joystick_mode and self.sm.recv_frame['testJoystick'] > 0 and self.sm['testJoystick'].buttons[0]:
|
||||
CC.cruiseControl.cancel = True
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ void MadsSettings::updateToggles() {
|
||||
const bool enable_mads = params.getBool("EnableMads");
|
||||
const bool enabled = is_offroad && enable_mads;
|
||||
|
||||
toggles["AccMadsCombo"]->setEnabled(enabled);
|
||||
toggles["MadsCruiseMain"]->setEnabled(enabled);
|
||||
toggles["AccMadsCombo"]->setEnabled(enable_mads);
|
||||
toggles["MadsCruiseMain"]->setEnabled(enable_mads);
|
||||
dlob_settings->setEnabled(enabled);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ def manager_init() -> None:
|
||||
("OsmDownloadedDate", "0"),
|
||||
("OSMDownloadProgress", "{}"),
|
||||
("SidebarTemperatureOptions", "0"),
|
||||
("SunnylinkEnabled", "0" if (build_metadata.release_channel or build_metadata.release_sp_channel) else "1"),
|
||||
("SunnylinkEnabled", "1"),
|
||||
("SunnylinkDongleId", f"{UNREGISTERED_SUNNYLINK_DONGLE_ID}"),
|
||||
("CustomDrivingModel", "0"),
|
||||
("DrivingModelGeneration", "4"),
|
||||
|
||||
@@ -33,6 +33,7 @@ OVERLAY_INIT = Path(os.path.join(BASEDIR, ".overlay_init"))
|
||||
|
||||
DAYS_NO_CONNECTIVITY_MAX = 14 # do not allow to engage after this many days
|
||||
DAYS_NO_CONNECTIVITY_PROMPT = 10 # send an offroad prompt after this many days
|
||||
params = Params()
|
||||
|
||||
class UserRequest:
|
||||
NONE = 0
|
||||
@@ -43,15 +44,18 @@ class WaitTimeHelper:
|
||||
def __init__(self):
|
||||
self.ready_event = threading.Event()
|
||||
self.user_request = UserRequest.NONE
|
||||
self.params = Params()
|
||||
signal.signal(signal.SIGHUP, self.update_now)
|
||||
signal.signal(signal.SIGUSR1, self.check_now)
|
||||
|
||||
def update_now(self, signum: int, frame) -> None:
|
||||
cloudlog.info("caught SIGHUP, attempting to downloading update")
|
||||
self.params.put("UpdaterState", "Update request received... Wait...")
|
||||
self.user_request = UserRequest.FETCH
|
||||
self.ready_event.set()
|
||||
|
||||
def check_now(self, signum: int, frame) -> None:
|
||||
self.params.put("UpdaterState", "Initializing updater to start check...")
|
||||
cloudlog.info("caught SIGUSR1, checking for updates")
|
||||
self.user_request = UserRequest.CHECK
|
||||
self.ready_event.set()
|
||||
@@ -119,6 +123,7 @@ def setup_git_options(cwd: str) -> None:
|
||||
]
|
||||
for option, value in git_cfg:
|
||||
run(["git", "config", option, value], cwd)
|
||||
params.put("UpdaterState", "Setting git options...")
|
||||
|
||||
|
||||
def dismount_overlay() -> None:
|
||||
@@ -141,7 +146,6 @@ def init_overlay() -> None:
|
||||
|
||||
cloudlog.info("preparing new safe staging area")
|
||||
|
||||
params = Params()
|
||||
params.put_bool("UpdateAvailable", False)
|
||||
set_consistent_flag(False)
|
||||
dismount_overlay()
|
||||
@@ -186,6 +190,7 @@ def finalize_update() -> None:
|
||||
set_consistent_flag(False)
|
||||
|
||||
# Copy the merged overlay view and set the update ready flag
|
||||
params.put("UpdaterState", "Copying the update to the final location...")
|
||||
if os.path.exists(FINALIZED):
|
||||
shutil.rmtree(FINALIZED)
|
||||
shutil.copytree(OVERLAY_MERGED, FINALIZED, symlinks=True)
|
||||
@@ -193,10 +198,13 @@ def finalize_update() -> None:
|
||||
run(["git", "reset", "--hard"], FINALIZED)
|
||||
run(["git", "submodule", "foreach", "--recursive", "git", "reset", "--hard"], FINALIZED)
|
||||
|
||||
params.put("UpdaterState", "Ensuring submodules are up-to-date...")
|
||||
cloudlog.info("Starting git cleanup in finalized update")
|
||||
t = time.monotonic()
|
||||
try:
|
||||
params.put("UpdaterState", "Doing git cleanup... (this may take a while)")
|
||||
run(["git", "gc"], FINALIZED)
|
||||
params.put("UpdaterState", "Still doing git cleanup...")
|
||||
run(["git", "lfs", "prune"], FINALIZED)
|
||||
cloudlog.event("Done git cleanup", duration=time.monotonic() - t)
|
||||
except subprocess.CalledProcessError:
|
||||
@@ -204,6 +212,7 @@ def finalize_update() -> None:
|
||||
|
||||
set_consistent_flag(True)
|
||||
cloudlog.info("done finalizing overlay")
|
||||
params.put("UpdaterState", "Finalizing update...")
|
||||
|
||||
|
||||
def handle_agnos_update() -> None:
|
||||
@@ -351,6 +360,7 @@ class Updater:
|
||||
self._has_internet = False
|
||||
|
||||
setup_git_options(OVERLAY_MERGED)
|
||||
params.put("UpdaterState", "Discovering branches...")
|
||||
output = run(["git", "ls-remote", "--heads"], OVERLAY_MERGED)
|
||||
|
||||
self.branches = defaultdict(lambda: None)
|
||||
@@ -360,19 +370,23 @@ class Updater:
|
||||
if x is not None and x.group('branch_name') not in excluded_branches:
|
||||
self.branches[x.group('branch_name')] = x.group('commit_sha')
|
||||
|
||||
params.put("UpdaterState", "Checking current branch...")
|
||||
cur_branch = self.get_branch(OVERLAY_MERGED)
|
||||
params.put("UpdaterState", "Checking current commit...")
|
||||
cur_commit = self.get_commit_hash(OVERLAY_MERGED)
|
||||
new_branch = self.target_branch
|
||||
new_commit = self.branches[new_branch]
|
||||
if (cur_branch, cur_commit) != (new_branch, new_commit):
|
||||
cloudlog.info(f"update available, {cur_branch} ({str(cur_commit)[:7]}) -> {new_branch} ({str(new_commit)[:7]})")
|
||||
upd_msg = f"update available, {cur_branch} ({str(cur_commit)[:7]}) -> {new_branch} ({str(new_commit)[:7]})"
|
||||
params.put("UpdaterState", upd_msg)
|
||||
cloudlog.info(upd_msg)
|
||||
else:
|
||||
cloudlog.info(f"up to date on {cur_branch} ({str(cur_commit)[:7]})")
|
||||
|
||||
def fetch_update(self) -> None:
|
||||
cloudlog.info("attempting git fetch inside staging overlay")
|
||||
|
||||
self.params.put("UpdaterState", "downloading...")
|
||||
self.params.put("UpdaterState", "Downloading... Please, wait.")
|
||||
|
||||
# TODO: cleanly interrupt this and invalidate old update
|
||||
set_consistent_flag(False)
|
||||
@@ -382,9 +396,13 @@ class Updater:
|
||||
|
||||
branch = self.target_branch
|
||||
git_fetch_output = run(["git", "fetch", "origin", branch], OVERLAY_MERGED)
|
||||
cloudlog.info("git fetch success: %s", git_fetch_output)
|
||||
upd_msg = f"git fetch success: {git_fetch_output}"
|
||||
self.params.put("UpdaterState", upd_msg)
|
||||
cloudlog.info(upd_msg)
|
||||
|
||||
cloudlog.info("git reset in progress")
|
||||
upd_msg = "git reset in progress"
|
||||
self.params.put("UpdaterState", upd_msg)
|
||||
cloudlog.info(upd_msg)
|
||||
cmds = [
|
||||
["git", "checkout", "--force", "--no-recurse-submodules", "-B", branch, "FETCH_HEAD"],
|
||||
["git", "reset", "--hard"],
|
||||
@@ -394,21 +412,21 @@ class Updater:
|
||||
["git", "submodule", "foreach", "--recursive", "git", "reset", "--hard"],
|
||||
]
|
||||
r = [run(cmd, OVERLAY_MERGED) for cmd in cmds]
|
||||
cloudlog.info("git reset success: %s", '\n'.join(r))
|
||||
self.params.put("UpdaterState", "git reset success...")
|
||||
cloudlog.info(f"git reset success: %s", '\n'.join(r))
|
||||
|
||||
# TODO: show agnos download progress
|
||||
if AGNOS:
|
||||
self.params.put("UpdaterState", "Checking AGNOS update...")
|
||||
handle_agnos_update()
|
||||
|
||||
# Create the finalized, ready-to-swap update
|
||||
self.params.put("UpdaterState", "finalizing update...")
|
||||
self.params.put("UpdaterState", "Finalizing update...")
|
||||
finalize_update()
|
||||
cloudlog.info("finalize success!")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
params = Params()
|
||||
|
||||
if params.get_bool("DisableUpdates"):
|
||||
cloudlog.warning("updates are disabled by the DisableUpdates param")
|
||||
exit(0)
|
||||
|
||||
Reference in New Issue
Block a user